home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume7 / rvi / part3 < prev    next >
Encoding:
Internet Message Format  |  1989-04-09  |  58.2 KB

  1. Subject:  v07i005:  Vi front-end for remote editing, Part03/04
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: Alan Klietz <ihnp4!dicome!mn-at1!alan>
  6. Mod.sources: Volume 7, Issue 5
  7. Archive-name: rvi/Part03
  8.  
  9. #!/bin/sh
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # Wrapped by mirror!rs on Wed Aug 27 00:09:58 EDT 1986
  13.  
  14. # Exit status; set to 1 on "wc" errors or if would overwrite.
  15. STATUS=0
  16. # Contents:  rv_insert.c rv_linecmd.c rv_misc.c rv_move.c
  17. #    rv_openline.c rv_put.c rv_redraw.c rv_redraw_ln.c rv_scroll.c
  18. #    rv_scroll_bk.c rv_search.c rv_shell.c rv_sync.c rv_undo.c
  19.  
  20. echo x - rv_insert.c
  21. if test -f rv_insert.c ; then
  22.     echo rv_insert.c exists, putting output in $$rv_insert.c
  23.     OUT=$$rv_insert.c
  24.     STATUS=1
  25. else
  26.     OUT=rv_insert.c
  27. fi
  28. sed 's/^XX//' > $OUT <<'@//E*O*F rv_insert.c//'
  29. XX#include "rv.h"
  30. XX#include <ctype.h>
  31.  
  32. XX#define ALLOC_LEN  64  /* Size of reallocation chunk */
  33.  
  34. XXboolean replace_flag;        /* TRUE if R command */
  35. XXboolean superquote;        /* Set by rv_getchar if char is quoted by ^V */
  36. XXextern INT autoindent;        /* Physical autoindent, if opened_line */
  37.  
  38. XX       char *fake_input;    /* Set this to fake text into rv_getchar */
  39. XXstatic char fake_buf[512];    /* Buffer for faked characters */
  40. XXextern char *realloc();
  41.  
  42.  
  43. XXvoid
  44. XXinsert()
  45. XX/*
  46. XX * Insert input at the current cursor position, replacing
  47. XX * text up to lastcol.  If lastcol < cursor, no text replaced.
  48. XX */
  49. XX{
  50. XX    register struct sc_screen *sc;
  51. XX    register struct li_line   *line;
  52. XX    boolean    quick_append;
  53. XX    INT    i;
  54. XX    char    *s, *indentbuf;
  55. XX    void    fake_chars();
  56.  
  57. XX    file.fi_modified = TRUE;
  58. XX    /*
  59. XX     * sc_firstcol = first column of insertion. Fixed.
  60. XX     * sc_lastcol  = last column of insertion.  Grows.
  61. XX     * sc_column   = current cursor position
  62. XX     */
  63.  
  64. XXnextinsert:
  65. XX    input_mode = TRUE;
  66. XX    quick_append = FALSE;
  67. XX    indentbuf = NULL;
  68. XX    save_Undo();
  69. XX    sc = &screen;
  70. XX    line = sc->sc_curline;
  71.  
  72. XX    if (!opened_line) {
  73. XX        /*
  74. XX         * Remember insertion for later undo
  75. XX         */
  76. XX        undo.un_firstline = sc->sc_firstline;
  77. XX        undo.un_lastline = sc->sc_lastline;
  78. XX        undo.un_validcol = TRUE;
  79. XX        undo.un_firstcol = sc->sc_firstcol;
  80. XX        undo.un_inserted = TRUE;
  81. XX        /*
  82. XX         * Save overwritten text for later undo
  83. XX         */
  84. XX        yank_cmd = ' ';
  85. XX        if (sc->sc_lastcol >= sc->sc_column) {
  86. XX            yank();
  87. XX            undo.un_deleted = TRUE;
  88. XX        }
  89. XX    } else if (autoindent > 0) {
  90. XX        /*
  91. XX         * Fake autoindented tabs and spaces into line
  92. XX         */
  93. XX        fake_input = fake_buf;
  94. XX        indentbuf = xalloc(autoindent+1);
  95. XX        i = autoindent / set_tabstops;
  96. XX        if (set_fortran)
  97. XX            fake_chars(' ', i * set_tabstops);
  98. XX        else
  99. XX            fake_chars('\t', i);
  100. XX        i = autoindent % set_tabstops;
  101. XX        fake_chars(' ', i);
  102. XX        fake_input = fake_buf;
  103. XX        strcpy(indentbuf, fake_input);
  104. XX    }
  105.  
  106. XX    if (sc->sc_lastcol >= sc->sc_column)
  107. XX        /*
  108. XX         * Append '$' to end of replaced text
  109. XX         */
  110. XX        line->li_text[sc->sc_lastcol] = '$';
  111.  
  112. XX    line->li_text = realloc(line->li_text, line->li_width + ALLOC_LEN + 1);
  113.  
  114. XX    /*
  115. XX     * Get and process input chars
  116. XX     */
  117. XX    for (;;) {
  118. XX        INT    ch;
  119.  
  120. XX        /*
  121. XX         * Redisplay line
  122. XX         * Append is a fast special case
  123. XX         */
  124. XX        if (quick_append)
  125. XX            quick_append = FALSE;
  126. XX        else {
  127. XX            redraw_curline(line->li_text);
  128. XX            move_cursor(sc->sc_lineno, sc->sc_column);
  129. XX        }
  130.  
  131. XX        ch = rv_getchar();
  132. XX        if (superquote) /* If quoted with ^V, skip all processing */
  133. XX            goto addchar;
  134.  
  135. XX        if (ch == erasechar() || ch == '\b') {
  136. XX            /*
  137. XX             * Delete a character if not blackslashed
  138. XX             */
  139. XX            if (sc->sc_column == sc->sc_firstcol) {
  140. XX                flash();
  141. XX                continue;
  142. XX            }
  143. XX            if (line->li_text[sc->sc_column-1] == '\\')
  144. XX                line->li_text[sc->sc_column-1] = ch;
  145. XX            else
  146. XX                sc->sc_column--;
  147. XX            continue;
  148. XX        }
  149.  
  150. XX        if (ch == killchar() || ch == CTRL(X)) {
  151. XX            /*
  152. XX             * Delete line if not backslashed
  153. XX             */
  154. XX            if (sc->sc_column == sc->sc_firstcol) {
  155. XX                /*
  156. XX                 * Already at first column, error
  157. XX                 */
  158. XX                flash();
  159. XX                continue;
  160. XX            }
  161. XX            if (line->li_text[sc->sc_column-1] == '\\')
  162. XX                line->li_text[sc->sc_column-1] = ch;
  163. XX            else
  164. XX                sc->sc_column = sc->sc_firstcol;
  165. XX            continue;
  166. XX        }
  167.  
  168. XX        switch (ch) {
  169. XXcase CTRL([):
  170. XXcase '\n':
  171. XXcase '\r':
  172. XX        /*
  173. XX         * Escape or newline - end insert
  174. XX         */
  175. XX        if (replace_flag) {
  176. XX            /*
  177. XX             * Clean up replace mode
  178. XX             */
  179. XX            if (sc->sc_column <= sc->sc_lastcol) {
  180. XX                register i;
  181. XX                /*
  182. XX                 * Replace backspaced chars from undo buffer
  183. XX                 */
  184. XX                for (i=sc->sc_column; i <= sc->sc_lastcol; ++i)
  185. XX                    if (i < sc->sc_origline.li_width)
  186. XX                        line->li_text[i] =
  187. XX                            sc->sc_origline.li_text[i];
  188. XX            }
  189. XX            /*
  190. XX             * Chop off backspaced chars at end of line
  191. XX             */
  192. XX            if (sc->sc_lastcol == line->li_width-1 &&
  193. XX                    sc->sc_lastcol >= 0) {
  194. XX                line->li_width = sc->sc_column;
  195. XX                line->li_text[line->li_width] = '\0';
  196. XX            }
  197. XX        } else { /* insert mode */
  198. XX            if (sc->sc_lastcol >= sc->sc_column) {
  199. XX                register char    *s, *s2;
  200. XX                /*
  201. XX                 * Close up backspaced text
  202. XX                 */
  203. XX                s  = &line->li_text[sc->sc_column];
  204. XX                s2 = &line->li_text[sc->sc_lastcol+1];
  205. XX                while (*s++ = *s2++)
  206. XX                    ;
  207. XX                line->li_width = strlen(line->li_text);
  208. XX            }
  209. XX        }
  210.  
  211. XX        /*
  212. XX         * Collapse autoindent if line not altered by user
  213. XX         */
  214. XX        if (opened_line && autoindent > 0 && indentbuf &&
  215. XX                strcmp(indentbuf, line->li_text) == 0) {
  216. XX            redraw_curline("");
  217. XX            sc->sc_column = 0;
  218. XX            i = autoindent;
  219. XX        } else {
  220. XX            redraw_curline(line->li_text);
  221. XX            i = 0;
  222. XX        }
  223. XX        if (indentbuf)
  224. XX            free(indentbuf);
  225.  
  226. XX        if (ch == CTRL([)) {
  227. XX            input_mode = FALSE;
  228. XX            replace_flag = FALSE;
  229. XX            if (sc->sc_column > 0)
  230. XX                sc->sc_column--;
  231. XX            move_cursor(sc->sc_lineno, sc->sc_column);
  232. XX            if (sc->sc_lastcol < sc->sc_firstcol) {
  233. XX                if (!opened_line)
  234. XX                    undo.un_inserted = FALSE;
  235. XX            } else
  236. XX                undo.un_lastcol = sc->sc_column;
  237. XX            return;
  238. XX        } else {
  239. XX            register char *s, *s2;
  240. XX            /*
  241. XX             * Continue input on new line
  242. XX             */
  243. XX            s = s2 = &line->li_text[sc->sc_column];
  244. XX            toss_undo();
  245. XX            openline(1);
  246. XX            if (i != 0)
  247. XX                autoindent = i;
  248. XX            if (*s != '\0') { /* if not at end of line */
  249. XX                /*
  250. XX                 * Split line
  251. XX                 */
  252. XX                undo.un_validcol = TRUE;
  253. XX                undo.un_firstcol = 0;
  254. XX                if (set_autoindent)
  255. XX                    while (isspace(*s))
  256. XX                        ++s;
  257. XX                redraw_curline(s);
  258. XX                xmit_curline();
  259. XX                *s2 = '\0';
  260. XX                sc->sc_lineno--;
  261. XX                sc->sc_curline--;
  262. XX                redraw_curline(sc->sc_curline->li_text);
  263. XX                save_Undo();
  264. XX                xmit_curline();
  265. XX                move_cursor(sc->sc_lineno+1, 0);
  266. XX                save_Undo();
  267. XX            }
  268. XX            goto nextinsert; /* quick recursion */
  269. XX        }
  270. XX        break;
  271.  
  272. XXcase CTRL(W):
  273. XX        /*
  274. XX         * Control-W - backspace 1 word
  275. XX         */
  276. XX        /* Implementation deferred */
  277. XX        continue;
  278.  
  279. XXcase '\t':
  280. XX        /*
  281. XX         * Tab
  282. XX         */
  283. XX        if (set_fortran) {
  284. XX            /*
  285. XX             * Fortran source.  Expand tab to spaces
  286. XX             */
  287. XX            if (sc->sc_column < 6) {
  288. XX                /*
  289. XX                 * First tab in fortran program, expand
  290. XX                 * to six spaces
  291. XX                 */
  292. XX                fake_input = fake_buf;
  293. XX                fake_chars(' ', 6-sc->sc_column);
  294. XX                fake_input = fake_buf;
  295. XX                continue;
  296. XX            }
  297. XX            /*
  298. XX             * Expand other tabs to shiftwidth spaces
  299. XX             */
  300. XX            i = set_shiftwidth - (sc->sc_column % set_shiftwidth);
  301. XX            fake_input = fake_buf;
  302. XX            fake_chars(' ', i);
  303. XX            fake_input = fake_buf;
  304. XX            continue;
  305. XX        }
  306. XX        break;
  307.  
  308.  
  309. XXcase CTRL(D):
  310. XX        /*
  311. XX         * Backtab
  312. XX         */
  313. XX        if (sc->sc_column == sc->sc_firstcol) {
  314. XX            flash();
  315. XX            continue;
  316. XX        }
  317. XX        i = screen_column(line->li_text, sc->sc_column);
  318. XX        i -= i % set_shiftwidth == 0 ?
  319. XX            set_shiftwidth : i % set_shiftwidth;
  320. XX        i = file_column(line->li_text, i);
  321. XX        if (set_fortran && i < 6 && sc->sc_column > 6)
  322. XX            i = 6;
  323. XX        fake_input = fake_buf;
  324. XX        fake_chars('\b', sc->sc_column - i);
  325. XX        fake_input = fake_buf;
  326. XX        continue;
  327.  
  328. XX        } /* End switch */
  329.  
  330. XX        
  331.  
  332. XX        /*
  333. XX         * Add character to line
  334. XX         */
  335.  
  336. XXaddchar:
  337. XX        /*
  338. XX         * Check if line needs expansion
  339. XX         */
  340. XX        if (sc->sc_lastcol < sc->sc_column) {
  341. XX            if (!replace_flag || sc->sc_column >= line->li_width) {
  342. XX                register  char *s, *s2;
  343. XX                /*
  344. XX                 * Expand line 1 character
  345. XX                 */
  346. XX                line->li_width++;
  347. XX                /*
  348. XX                 * Expand line in chunks of ALLOC_LEN
  349. XX                 */
  350. XX                if (line->li_width % ALLOC_LEN == 0)
  351. XX                    line->li_text = realloc(line->li_text,
  352. XX                        line->li_width + ALLOC_LEN+1);
  353.  
  354. XX                if (sc->sc_column == line->li_width-1 && 
  355. XX                    ch >= '@' && CURCOLUMN > 0) {
  356. XX                    /*
  357. XX                     * Fast special case - add char at
  358. XX                     * eol.  No control chars, no char, 
  359. XX                     * shifting, and no line shifting
  360. XX                     * required.
  361. XX                     */
  362. XX                    quick_append = TRUE;
  363. XX                    addch(ch);
  364. XX                    line->li_text[line->li_width] = '\0';
  365. XX#ifndef USG
  366. XX                    /*
  367. XX                     * KLUDGE - Handle VT100 brain damage
  368. XX                     * until Berkeley fixes up curses to 
  369. XX                     * handle it.
  370. XX                     */
  371. XX                    if (XN && CURCOLUMN==0) {
  372. XX                        addch(' ');
  373. XX                        refresh();
  374. XX                        addch('\b');
  375. XX                    }
  376. XX#endif
  377. XX                } else {
  378. XX                    /*
  379. XX                     * Slide text beyond insert right
  380. XX                     */
  381. XX                    s  = &line->li_text[line->li_width-1];
  382. XX                    s2 = &line->li_text[sc->sc_column];
  383. XX                    while (s >= s2) {
  384. XX                        *(s+1) = *s;
  385. XX                        --s;
  386. XX                    }
  387. XX                }
  388. XX            }
  389. XX            sc->sc_lastcol++;
  390. XX            if (sc->sc_lastcol < sc->sc_firstcol)
  391. XX                sc->sc_lastcol = sc->sc_firstcol;
  392. XX        }
  393.  
  394. XX        /*
  395. XX         * Insert character
  396. XX         */
  397. XX        line->li_text[sc->sc_column++] = ch;
  398. XX    }
  399. XX}
  400.  
  401.  
  402. XXINT
  403. XXrv_getchar()
  404. XX/*
  405. XX * Get a character from the keyboard.  
  406. XX * Parse ^V as a super quote.
  407. XX */
  408. XX{
  409. XX    INT ch;
  410.  
  411. XX    superquote = FALSE;
  412. XX    /*
  413. XX     * Check for fake input
  414. XX     */
  415. XX    if (fake_input && *fake_input != '\0')
  416. XX        return(*fake_input++);
  417.  
  418. XX    refresh();
  419. XX    while ((ch = getch()) == '\0') /* null is verboten */
  420. XX        ;
  421. XX    if (ch == CTRL(V)) {
  422. XX        raw(); /* Allow ^S, ^Q and interrupt keys */
  423. XX        insch('^');
  424. XX        /*
  425. XX         * Get raw character, null is verboten.
  426. XX         */
  427. XX        refresh();
  428. XX        while ((ch = getch()) == '\0')
  429. XX            ;
  430. XX        noraw();
  431. XX#ifdef USG
  432. XX        cbreak();
  433. XX#else
  434. XX        crmode();
  435. XX#endif !USG
  436. XX        superquote = (ch != '\n');
  437. XX    }
  438. XX    if (ch == ERR || ch == EOF)
  439. XX        quit();
  440. XX    return(ch);
  441. XX}
  442.  
  443.  
  444. XXvoid
  445. XXdup_insert(count)
  446. XX/*
  447. XX * Duplicate the text found between firstcol and column
  448. XX */
  449. XXINT count;
  450. XX{
  451. XX    register struct sc_screen *sc;
  452. XX    register struct li_line   *line;
  453. XX    register char    *buf, *s, *s1, *s2;
  454.  
  455. XX    sc = &screen;
  456. XX    line = sc->sc_curline;
  457.  
  458. XX    /*
  459. XX     * Make sure duplicatable section exists
  460. XX     */
  461. XX    if (count <= 1 || sc->sc_column  < sc->sc_firstcol
  462. XX               || sc->sc_lastcol < sc->sc_firstcol)
  463. XX        return;
  464.  
  465. XX    sc->sc_column++;
  466. XX    /*
  467. XX     * Get buffer space
  468. XX     */
  469. XX    buf = xalloc(strlen(line->li_text)+1 + (sc->sc_column -
  470. XX                         sc->sc_firstcol) * count);
  471. XX    /*
  472. XX     * Copy text up to duplicatable section
  473. XX     */
  474. XX    s = buf;
  475. XX    s1 = line->li_text;
  476. XX    s2 = &line->li_text[sc->sc_column];
  477. XX    while (s1 < s2)
  478. XX        *s++ = *s1++;
  479.  
  480. XX    /*
  481. XX     * Duplicate section
  482. XX     */
  483. XX    while (--count > 0) {
  484. XX        s1 = &line->li_text[sc->sc_firstcol];
  485. XX        while (s1 < s2)
  486. XX            *s++ = *s1++;
  487. XX    }
  488.  
  489. XX    /*
  490. XX     * Position cursor at last character of last duplicated section
  491. XX     */
  492. XX    sc->sc_column = (s - buf) - 1;
  493.  
  494. XX    /*
  495. XX     * Set up for undo
  496. XX     */
  497. XX    if (!opened_line) {
  498. XX        undo.un_inserted = TRUE;
  499. XX        undo.un_validcol = TRUE;
  500. XX        undo.un_firstline = undo.un_lastline = sc->sc_lineno;
  501. XX        undo.un_firstcol = sc->sc_firstcol;
  502. XX        undo.un_lastcol = sc->sc_column;
  503. XX    }
  504.  
  505. XX    /*
  506. XX     * Copy remainder of line
  507. XX     */
  508. XX    while (*s++ = *s2++)
  509. XX        ;
  510. XX    redraw_curline(buf);
  511. XX    free(buf);
  512. XX    move_cursor(sc->sc_lineno, sc->sc_column);
  513. XX}
  514.  
  515.  
  516. XXvoid
  517. XXfake_chars(ch, count)
  518. XXchar ch;
  519. XXregister INT count;
  520. XX{
  521. XX    register char *s;
  522.  
  523. XX    s = fake_input;
  524. XX    for (; count > 0; --count)
  525. XX        *s++ = ch;
  526. XX    *s = '\0';
  527. XX    fake_input = s;
  528. XX}
  529. @//E*O*F rv_insert.c//
  530. chmod u=rw,g=rw,o=rw $OUT
  531.  
  532. echo x - rv_linecmd.c
  533. if test -f rv_linecmd.c ; then
  534.     echo rv_linecmd.c exists, putting output in $$rv_linecmd.c
  535.     OUT=$$rv_linecmd.c
  536.     STATUS=1
  537. else
  538.     OUT=rv_linecmd.c
  539. fi
  540. sed 's/^XX//' > $OUT <<'@//E*O*F rv_linecmd.c//'
  541. XX#include "rv.h"
  542. XX#include <ctype.h>
  543.  
  544. XXboolean    ed_undo;    /* Set TRUE if last mod was direct ed cmd */
  545.  
  546. XXextern boolean did_botprint;   /* used by botprint() */
  547.  
  548. XXstatic struct cm_cmdlist {  /* Commands */
  549. XX    char cm_cmd[12];
  550. XX    INT  cm_index;
  551. XX} cmdlist[] = {
  552. XX    "E",    3,
  553. XX    "Q",    2,
  554. XX    "edit", 3,
  555. XX    "file", 5,
  556. XX    "next", 4,
  557. XX    "quit",    2,
  558. XX    "se",    1,
  559. XX    "set",    1,
  560. XX    "sh",    8,
  561. XX    "shell",8,
  562. XX    "w",    6,
  563. XX    "wq",    7,
  564. XX    "write", 6,
  565. XX    "xit",    7,
  566. XX    "z",    7,
  567. XX};
  568.  
  569. XXstatic struct op_oplist {   /* Options */
  570. XX    char op_option[12];
  571. XX    INT  op_index;
  572. XX} oplist[] = {
  573. XX    "ai",        1,
  574. XX    "all",        2,
  575. XX    "autoindent",     1,
  576. XX    "debug",    3,
  577. XX    "fortran",    4,
  578. XX    "list",        5,
  579. XX    "scroll",    6,
  580. XX    "shiftwidth",    7,
  581. XX    "sw",        7,
  582. XX    "tabstops",    8,
  583. XX    "timeout",    10,
  584. XX    "to",        10,
  585. XX    "ts",        8,
  586. XX    "wrapscan",    9,
  587. XX    "ws",        9,
  588. XX};
  589.  
  590.  
  591. XXvoid
  592. XXrv_linecmd(cmd)
  593. XX/*
  594. XX * Execute command line
  595. XX */
  596. XXchar *cmd;
  597. XX{
  598. XX    register char *s, *s2;
  599. XX    INT    i, j;
  600. XX    boolean    flag;
  601. XX    char    buf[12];
  602. XX    
  603. XX    if ((s2 = cmd) == NULL || *s2 == '\0')
  604. XX        return;
  605. XX    while (isalnum(*s2))
  606. XX        ++s2;
  607. XX    j = *s2;
  608. XX    *s2 = '\0';
  609. XX    i = binsearch(cmd, (char *) cmdlist, sizeof(struct cm_cmdlist),
  610. XX        sizeof(cmdlist) / sizeof(struct cm_cmdlist));
  611. XX    if (i >= 0)
  612. XX        i = cmdlist[i].cm_index;
  613. XX    *s2 = j;
  614.  
  615. XX    xmit_curline();
  616. XX    switch(i) {
  617. XXcase 1:
  618. XX    /*
  619. XX     * Set
  620. XX     */
  621. XX    if (*s2 == '\0')
  622. XX        s2 = "all";
  623. XX    for (;;) {
  624. XX        while (isspace(*s2) && *s2 != '\0')
  625. XX            ++s2;
  626. XX        if (*s2 == '\0')
  627. XX            break;
  628. XX        s = s2;
  629. XX        while (isalnum(*s2))
  630. XX            ++s2;
  631. XX        if (*s2 != '\0')
  632. XX            *s2++ = '\0';
  633. XX        if (*s == 'n' && *(s+1) == 'o') {
  634. XX            s += 2;
  635. XX            flag = FALSE;
  636. XX        } else
  637. XX            flag = TRUE;
  638. XX        i = binsearch(s, (char *) oplist, sizeof(struct op_oplist),
  639. XX            sizeof(oplist) / sizeof(struct op_oplist));
  640. XX        if (i >= 0)
  641. XX            i = oplist[i].op_index;
  642.  
  643. XX        switch (i) {
  644.  
  645. XX        case -2:
  646. XX            botprint(TRUE, "\"%s\" is not unique\n", s);
  647. XX            break;
  648.  
  649. XX        case -1:
  650. XX            botprint(TRUE, "\"%s\": No such option - 'set all' gives all option values\n", s);
  651. XX            return;
  652.  
  653. XX        case 1: /* autoindent */
  654. XX            set_autoindent = flag;
  655. XX            break;
  656. XX        
  657. XX        case 2: /* all */
  658. XX            botprint(FALSE, "%sautoindent\n", set_autoindent ?
  659. XX                "" : "no");
  660. XX            botprint(FALSE, "debug=%d\n", set_debug);
  661. XX            botprint(FALSE, "%sfortran\n", set_fortran ? "" :
  662. XX                "no");
  663. XX            botprint(FALSE, "%slist", set_list ? "" : "no");
  664. XX            botprint(FALSE, "scroll=%d\n", set_scroll);
  665. XX            botprint(FALSE, "shiftwidth=%d\n", set_shiftwidth);
  666. XX            botprint(FALSE, "tabstops=%d\n", set_tabstops);
  667. XX            botprint(FALSE, "%stimeout", set_timeout ? "" : "no");
  668. XX            botprint(FALSE, "%swrapscan", set_wrapscan ? "" : "no");
  669. XX            break;
  670.  
  671. XX        case 3: /* debug */
  672. XX            set_debug = atoi(s2);
  673. XX            while (isdigit(*s2))
  674. XX                ++s2;
  675. XX            break;
  676.  
  677. XX        case 4:
  678. XX            set_fortran = flag;
  679. XX            break;
  680.  
  681. XX        case 5: set_list = flag;
  682. XX            fetch_window(screen.sc_lineno-NUM_WINDOW_LINES/4-
  683. XX                LINES-2+1, TRUE);
  684. XX            break;
  685.  
  686. XX        case 6: /* scroll */
  687. XX            set_scroll = atoi(s2);
  688. XX            while (isdigit(*s2))
  689. XX                ++s2;
  690. XX            if (set_scroll <= 0)
  691. XX                set_scroll = 1;
  692. XX            break;
  693.  
  694. XX        case 7: /* shiftwidth */
  695. XX            set_shiftwidth = atoi(s2);
  696. XX            while (isdigit(*s2))
  697. XX                ++s2;
  698. XX            if (set_shiftwidth <= 0)
  699. XX                set_shiftwidth = 1;
  700. XX            else if (set_shiftwidth > 40)
  701. XX                set_shiftwidth = 40;
  702. XX            break;
  703.  
  704. XX        case 8: /* tabstops */
  705. XX            set_tabstops = atoi(s2);
  706. XX            while (isdigit(*s2))
  707. XX                ++s2;
  708. XX            if (set_tabstops <= 0)
  709. XX                set_tabstops = 1;
  710. XX            else if (set_tabstops > 40)
  711. XX                set_tabstops = 40;
  712. XX            break;
  713.  
  714. XX        case 9: /* wrapscan */
  715. XX            set_wrapscan = flag;
  716. XX            break;
  717.  
  718. XX        case 10: /* timeout */
  719. XX            set_timeout = flag;
  720. XX#ifdef USG
  721. XX            keypad(stdscr, flag ? 1 : 2);
  722. XX#endif
  723. XX            break;
  724.  
  725. XX        default:
  726. XX            botprint(FALSE, "That option is not yet implemented\n");
  727. XX            break;
  728. XX        }
  729. XX    }
  730. XX    break;
  731.  
  732.  
  733. XXcase 2: /* quit */
  734. XX    if (file.fi_modified && *s2 != '!') {
  735. XX        botprint(TRUE, "No write since last change (:q! overrides)");
  736. XX        return;
  737. XX    }
  738. XX    Quit();
  739. XX    break;
  740.  
  741. XXcase 3: /* edit */
  742. XX    if (file.fi_modified && *s2 != '!') {
  743. XX        botprint(TRUE, "No write since last change (:edit! overrides)");
  744. XX        return;
  745. XX    }
  746. XX    if (*s2 == '!')
  747. XX        ++s2;
  748. XX    while (isspace(*s2))
  749. XX        ++s2;
  750. XX    edit(s2);
  751. XX    break;
  752.  
  753. XXcase 4: /* next */
  754. XX    if (file.fi_modified && *s2 != '!') {
  755. XX        botprint(TRUE, "No write since last change (:next! overrides)");
  756. XX        return;
  757. XX    }
  758. XX    if (*s2 == '!')
  759. XX        ++s2;
  760. XX    while (isspace(*s2))
  761. XX        ++s2;
  762. XX    if (*s2 == '\0' && *nextfile == '\0') {
  763. XX        botprint(TRUE, "No more files to edit");
  764. XX        return;
  765. XX    }
  766. XX    edit(s2);
  767. XX    break;
  768.  
  769. XXcase 5: /* file */
  770. XX    while (isspace(*s2))
  771. XX        ++s2;
  772. XX    if (*s2 == '\0') {
  773. XX        sizemsg();
  774. XX        return;
  775. XX    }
  776. XX    xmit_ed("f %s\n", s2);
  777. XX    strncpy(file.fi_name, s2, 126);
  778. XX    xmit_sync();
  779. XX    (void) recv_sync(TRUE);
  780. XX    sizemsg();
  781. XX    break;
  782.  
  783. XXcase 6: /* write */
  784. XX    i = 0;
  785. XX    if (*s2 == '!') {
  786. XX        ++s2;
  787. XX        i = 1;
  788. XX    }
  789. XX    while (isspace(*s2))
  790. XX        ++s2;
  791. XX    if (*s2 == '\0' && file.fi_name[0] == '\0') {
  792. XX        botprint(TRUE, "No current filename");
  793. XX        return;
  794. XX    }
  795. XX    if (i)
  796. XX        xmit_ed("!rm -f %s\n", *s2 ? s2 : file.fi_name);
  797. XX    if (*s2)
  798. XX        xmit_ed("w %s\n", s2);
  799. XX    else {
  800. XX        xmit_ed("w\n");
  801. XX        s2 = file.fi_name;
  802. XX    }
  803. XX    xmit_sync();
  804. XX    botprint(FALSE, "\"%s\"", s2);
  805. XX    hitcr_continue();
  806. XX    refresh();
  807. XX    if (recv_sync(TRUE)) {
  808. XX        botprint(FALSE, "\"%s\" %d lines", s2, file.fi_numlines);
  809. XX        if (strcmp(s2, file.fi_name) == 0)
  810. XX            file.fi_modified = FALSE;
  811. XX    }
  812. XX    else
  813. XX        hitcr_continue();
  814. XX    break;
  815.  
  816. XXcase 7: /* wq */
  817. XX    if (file.fi_modified)
  818. XX        rv_linecmd("w");
  819. XX    if (!file.fi_modified)
  820. XX        rv_linecmd("q");
  821. XX    break;
  822.  
  823. XXcase 8: /* shell */
  824. XX    rv_shell("sh -i");
  825. XX    break;
  826. XX    
  827. XXdefault:
  828. XX    if (*s2 == '!') {  /* Shell escape */
  829. XX        if (strcmp(++s2, "sh") == 0)
  830. XX            s2 = "sh -i";
  831. XX        else if (strcmp(s2, "csh") == 0)
  832. XX            s2 = "csh -i";
  833. XX        rv_shell(s2);
  834. XX        return;
  835. XX    }
  836. XX    did_botprint = TRUE;
  837. XX    i = cmd[strlen(cmd)-1];
  838. XX    if (i == 'a' || i == 'c' || i == 'i' || i == 'H' || i == 'X'
  839. XX             || i == 'P') {
  840. XX        botprint(FALSE, "That command is reserved");
  841. XX        return;
  842. XX    }
  843. XX    toss_undo();
  844. XX    if (i == 'w') {
  845. XX        ed_undo = FALSE;
  846. XX        file.fi_modified = FALSE;
  847. XX    } else
  848. XX        ed_undo = TRUE;
  849. XX    xmit_ed("%d\n", screen.sc_lineno);
  850. XX    xmit_sync();
  851. XX    xmit_ed("%s\n", cmd);
  852. XX    xmit_sync();
  853. XX    xmit_ed(".=\n");
  854. XX    (void) recv_sync(FALSE);
  855. XX    (void) recv_sync(2);
  856. XX    (void) fgets(buf, 10, file.fi_fpin);
  857. XX    if ((i = atoi(buf)) <= 0)
  858. XX        i = screen.sc_lineno;
  859. XX    hitcr_continue();
  860. XX    fetch_window(i-NUM_WINDOW_LINES/4-LINES/2+1, TRUE);
  861. XX    move_abs_cursor(i, COL_FIRST_NONWHITE);
  862. XX    break;
  863. XX    }
  864. XX}
  865. @//E*O*F rv_linecmd.c//
  866. chmod u=rw,g=rw,o=rw $OUT
  867.  
  868. echo x - rv_misc.c
  869. if test -f rv_misc.c ; then
  870.     echo rv_misc.c exists, putting output in $$rv_misc.c
  871.     OUT=$$rv_misc.c
  872.     STATUS=1
  873. else
  874.     OUT=rv_misc.c
  875. fi
  876. sed 's/^XX//' > $OUT <<'@//E*O*F rv_misc.c//'
  877. XX#include "rv.h"
  878.  
  879. XX/*
  880. XX * Miscellaneous subroutines
  881. XX */
  882.  
  883. XXchar *xalloc(n)
  884. XX/*
  885. XX * Allocate and zero n bytes
  886. XX */
  887. XX{
  888. XX    char *s;
  889. XX    char *malloc();
  890.  
  891. XX    if ((s = malloc(n)) == NULL) {
  892. XX        write(2, "Out of memory", 13);
  893. XX        endwin();
  894. XX        exit(1);
  895. XX    }
  896. XX    zero(s, n);
  897. XX    return s;
  898. XX}
  899.  
  900.  
  901. XXboolean did_botprint;  /* True if botprint() was already called */
  902. XXboolean scrolled;      /* True if screen scrolled from a call */
  903.  
  904. XX/*VARARGS1*/
  905. XXvoid
  906. XXbotprint(standout_flag, txt, arg1, arg2, arg3, arg4, arg5)
  907. XX/*
  908. XX * Printf line(s) on bottom of screen with the given attribute(s).
  909. XX */
  910. XXINT  standout_flag;
  911. XXchar *txt, *arg1, *arg2, *arg3, *arg4, *arg5;
  912. XX{
  913. XX    char buf[512];
  914. XX    INT  oldrow, oldcol, l;
  915.  
  916. XX    oldrow = CURLINE;
  917. XX    oldcol = CURCOLUMN;
  918.  
  919. XX    sprintf(buf, txt, arg1, arg2, arg3, arg4, arg5);
  920. XX    l = strlen(buf);
  921. XX    if (l > 0 && buf[l-1] == '\n') /* Remove trailing \n */
  922. XX        buf[--l] = '\0';
  923. XX    move(LINES-1, 0);
  924. XX    if (did_botprint) {
  925. XX        rv_fscroll(1);
  926. XX        move(LINES-1, 0);
  927. XX        scrolled = TRUE;
  928. XX    }
  929. XX    else
  930. XX        clrtoeol();
  931.  
  932. XX    if (standout_flag)
  933. XX        standout();
  934. XX    addstr(buf);
  935. XX    if (standout_flag)
  936. XX        standend();
  937. XX    while (l > 0 && buf[l-1] == '\n') {
  938. XX        buf[--l] = '\0';
  939. XX        /* scroll(stdscr); */
  940. XX        scrolled = TRUE;
  941. XX    }
  942.  
  943. XX    did_botprint = TRUE;
  944.  
  945. XX    if (l >= COLS || l > CURCOLUMN)
  946. XX        scrolled = TRUE;
  947.  
  948. XX    move(oldrow, oldcol);
  949. XX}
  950.  
  951.  
  952. XXhitcr_continue()
  953. XX{
  954. XX    INT oldrow, oldcol;
  955. XX    INT c;
  956.  
  957. XX    if (scrolled) {
  958. XX        /*
  959. XX         * Screen scrolled.  Redraw
  960. XX         */
  961. XX        oldrow = CURLINE;
  962. XX        oldcol = CURCOLUMN;
  963. XX        move(LINES-1,0);
  964. XX        rv_fscroll(1);
  965. XX        move(LINES-1, 0);
  966. XX        standout();
  967. XX        addstr("[Hit return to continue]");
  968. XX        standend();
  969. XX        refresh();
  970. XX        while ((c = getch()) != '\r' && c != '\n' && c != ' ')
  971. XX            ;
  972. XX        redraw_screen((struct li_line *) 0);
  973. XX        move(oldrow, oldcol);
  974. XX        scrolled = FALSE;
  975. XX    }
  976. XX    did_botprint = FALSE;
  977. XX}
  978.  
  979.  
  980. XXvoid
  981. XXpanic(msg)
  982. XX/*
  983. XX * Print msg and abort
  984. XX */
  985. XXchar *msg;
  986. XX{
  987. XX    botprint(TRUE, "Fatal error: %s\n", msg);
  988. XX    move(LINES-1, 0);
  989. XX    rv_fscroll(1);
  990. XX    move(LINES-1, 0);
  991. XX    refresh();
  992. XX    endwin();
  993. XX    exit(1);
  994. XX}
  995.  
  996. XXvoid
  997. XXsizemsg()
  998. XX{
  999. XX    if (file.fi_name[0] == '\0' || strcmp(file.fi_name, "/dev/null") == 0)
  1000. XX        botprint(0, "No file  line %d of %d --%d%%--", 
  1001. XX            screen.sc_lineno, file.fi_numlines, 
  1002. XX            (screen.sc_lineno*100) / file.fi_numlines);
  1003. XX    else
  1004. XX        botprint(0, "\"%s\" %sline %d of %d --%d%%--", file.fi_name,
  1005. XX            file.fi_modified ? "[modified] " : "",
  1006. XX            screen.sc_lineno, file.fi_numlines, 
  1007. XX            (screen.sc_lineno*100) / file.fi_numlines);
  1008. XX}
  1009.  
  1010.  
  1011. XXvoid
  1012. XXrv_debug()
  1013. XX{
  1014. XX    botprint(FALSE, "Absolute:\n");
  1015. XX    botprint(FALSE, "wi_topline=%d, wi_botline=%d\n",
  1016. XX        window.wi_topline - &line_array[0],
  1017. XX        window.wi_botline - &line_array[0]);
  1018. XX    botprint(FALSE, "sc_topline=%d, sc_botline=%d, sc_curline=%d\n",
  1019. XX        screen.sc_topline - &line_array[0],
  1020. XX        screen.sc_botline - &line_array[0],
  1021. XX        screen.sc_curline - &line_array[0]);
  1022. XX    botprint(FALSE, "sc_lineno=%d, fi_numlines=%d\n",
  1023. XX        screen.sc_lineno, file.fi_numlines);
  1024. XX    botprint(FALSE, "Relative to window:\n");
  1025. XX    botprint(FALSE, "sc_topline=%d, sc_botline=%d, sc_curline=%d\n",
  1026. XX        screen.sc_topline - window.wi_topline,
  1027. XX        screen.sc_botline - window.wi_topline,
  1028. XX        screen.sc_curline - window.wi_topline);
  1029. XX}
  1030. @//E*O*F rv_misc.c//
  1031. chmod u=rw,g=rw,o=rw $OUT
  1032.  
  1033. echo x - rv_move.c
  1034. if test -f rv_move.c ; then
  1035.     echo rv_move.c exists, putting output in $$rv_move.c
  1036.     OUT=$$rv_move.c
  1037.     STATUS=1
  1038. else
  1039.     OUT=rv_move.c
  1040. fi
  1041. sed 's/^XX//' > $OUT <<'@//E*O*F rv_move.c//'
  1042. XX#include "rv.h"
  1043. XX#include <ctype.h>
  1044.  
  1045. XX/*
  1046. XX * rv_move.c  - Cursor motion routines
  1047. XX */
  1048.  
  1049. XXvoid
  1050. XXmove_abs_cursor(lineno, column)
  1051. XX/*
  1052. XX * Move cursor to absolute position in file.  Try to stay within the window
  1053. XX * if possible.
  1054. XX */
  1055. XXINT lineno, column;
  1056. XX{
  1057. XX    register INT    seg;
  1058. XX    register struct li_line    *line, *newline;
  1059. XX    register struct sc_screen      *sc;
  1060. XX    register struct wi_window      *wi;
  1061. XX    INT     oldlineno, offset;
  1062. XX    struct   fi_file           *fi;
  1063. XX    void     rv_scroll(), rv_scroll_backward();
  1064.  
  1065. XX    sc = &screen;
  1066. XX    wi = &window;
  1067. XX    fi = &file;
  1068. XX    errflag = 0;
  1069. XX    /*
  1070. XX     * Boundary checks
  1071. XX     */
  1072. XX    if (lineno < 1) { /* If past top of file */
  1073. XX        errflag = 1;
  1074. XX        flash();
  1075. XX        return;
  1076. XX    } else if (lineno > fi->fi_numlines) { /* If past bottom of file */
  1077. XX        errflag = 1;
  1078. XX        flash();
  1079. XX        return;
  1080. XX    }
  1081.  
  1082. XX    if (lineno < sc->sc_lineno - (sc->sc_curline-sc->sc_topline)) {
  1083. XX        /*
  1084. XX         * Past top of screen
  1085. XX         */
  1086. XX        oldlineno = sc->sc_lineno;
  1087. XX        if (lineno < sc->sc_lineno - (sc->sc_curline-wi->wi_topline)) {
  1088. XX            /*
  1089. XX             * Past top of window, fetch more data
  1090. XX             */
  1091. XX            fetch_window(lineno-NUM_WINDOW_LINES/4-LINES/2+1,
  1092. XX                                    FALSE);
  1093. XX            if (errflag)
  1094. XX                return;
  1095. XX        }
  1096. XX        newline = sc->sc_curline - (sc->sc_lineno - lineno);
  1097. XX        seg = 0;
  1098. XX        if (oldlineno == sc->sc_lineno) { /* If relatively close */
  1099. XX            /*
  1100. XX             * Find distance, in segments, above top of screen
  1101. XX             */
  1102. XX            for (line = newline; line < sc->sc_topline; ++line)
  1103. XX                seg += line->li_segments;
  1104. XX            if (seg <= LINES/3+1) { /* If very close */
  1105. XX                /*
  1106. XX                 * Scroll backwards
  1107. XX                 */
  1108. XX                rv_scroll_backward(sc->sc_topline - newline);
  1109. XX                move_cursor(lineno, column);
  1110. XX                return;
  1111. XX            }
  1112. XX        }
  1113.  
  1114. XX        /*
  1115. XX         * Newline is too far away for scrolling,
  1116. XX         * so we redraw the screen and deposit newline
  1117. XX         * in the center.
  1118. XX         */
  1119.  
  1120. XX        /*
  1121. XX         * Set the top of the screen at LINES/2 segments above newline
  1122. XX         */
  1123. XX        xmit_curline();
  1124. XX        seg = LINES/2;
  1125. XX        for (line = newline; line >= wi->wi_topline && seg > 0; --line)
  1126. XX            seg -= line->li_segments;
  1127. XX        sc->sc_topline = line+1;
  1128. XX        sc->sc_curline = newline;
  1129. XX        sc->sc_lineno = lineno;
  1130. XX        sc->sc_abovetop = 0;
  1131. XX        /*
  1132. XX         * Compute bottom line
  1133. XX         */
  1134. XX        line = sc->sc_topline;
  1135. XX        for (seg = line->li_segments; seg < LINES;
  1136. XX                seg += line->li_segments) {
  1137. XX            ++line;
  1138. XX            if (line > wi->wi_botline)
  1139. XX                break;
  1140. XX        }
  1141. XX        sc->sc_botline = line-1;
  1142.  
  1143. XX        /*
  1144. XX         * Update the screen to curses
  1145. XX         */
  1146. XX        move_cursor(lineno, column);
  1147. XX        redraw_screen((struct li_line *)0);
  1148. XX        return;
  1149. XX    } /* End of past top of screen */
  1150. XX        
  1151.  
  1152. XX    if (lineno > sc->sc_lineno + (sc->sc_botline - sc->sc_curline)) {
  1153. XX        /*
  1154. XX         * Past bottom of screen
  1155. XX         */
  1156. XX        oldlineno = sc->sc_lineno;
  1157. XX        offset = sc->sc_botline - sc->sc_curline;
  1158. XX        if (lineno > sc->sc_lineno + (wi->wi_botline-sc->sc_curline)) {
  1159. XX            /*
  1160. XX             * Past bottom of window
  1161. XX             */
  1162. XX            fetch_window(lineno-NUM_WINDOW_LINES/4-LINES/2+1,
  1163. XX                                    TRUE);
  1164. XX            if (errflag)
  1165. XX                return;
  1166. XX        }
  1167. XX        newline = sc->sc_curline + (lineno - sc->sc_lineno);
  1168. XX        seg = 0;
  1169. XX        if (oldlineno == sc->sc_lineno) { /* If relatively close */
  1170. XX            /*
  1171. XX             * Find distance in segments past bottom of screen
  1172. XX             */
  1173. XX            for (line = sc->sc_curline+offset+1; line <= newline;
  1174. XX                                    ++line)
  1175. XX                seg += line->li_segments;
  1176. XX            if (seg <= LINES/3+1 && newline >= sc->sc_botline) {
  1177. XX                /*
  1178. XX                 * Scroll screen forwards
  1179. XX                 */
  1180. XX                rv_scroll(newline - sc->sc_botline);
  1181. XX                move_cursor(lineno, column);
  1182. XX                return;
  1183. XX            }
  1184. XX        }
  1185.  
  1186. XX        /*
  1187. XX         * Newline is too far away for scrolling,
  1188. XX         * so we redraw the screen and deposit newline
  1189. XX         * in the center.
  1190. XX         */
  1191.  
  1192. XX        /*
  1193. XX         * Set the top of the screen at LINES/2 segments above newline
  1194. XX         */
  1195. XX        xmit_curline();
  1196. XX        seg = LINES/2;
  1197. XX        for (line = newline; line >= wi->wi_topline && seg > 0; --line)
  1198. XX            seg -= line->li_segments;
  1199. XX        sc->sc_abovetop = 0;
  1200. XX        sc->sc_topline = line+1;
  1201. XX        sc->sc_curline = newline;
  1202. XX        sc->sc_lineno = lineno;
  1203. XX        /*
  1204. XX         * Compute bottom line
  1205. XX         */
  1206. XX        line = sc->sc_topline;
  1207. XX        for (seg = line->li_segments; seg < LINES;
  1208. XX                seg += line->li_segments) {
  1209. XX            ++line;
  1210. XX            if (line > wi->wi_botline)
  1211. XX                break;
  1212. XX        }
  1213. XX        sc->sc_botline = line-1;
  1214.  
  1215. XX        /*
  1216. XX         * Update the screen to curses
  1217. XX         */
  1218. XX        move_cursor(lineno, column);
  1219. XX        redraw_screen((struct li_line *)0);
  1220. XX        return;
  1221. XX    } /* End of past bottom of screen */
  1222. XX        
  1223. XX    /*
  1224. XX     * Otherwise, newline must already be on the screen
  1225. XX     */
  1226.  
  1227. XX    move_cursor(lineno, column);
  1228. XX    return;
  1229. XX}
  1230.  
  1231.  
  1232.  
  1233. XXvoid
  1234. XXmove_cursor(lineno, column)
  1235. XX/*
  1236. XX * Move cursor to position in file.  Must already be on screen.
  1237. XX */
  1238. XXINT lineno, column;
  1239. XX{
  1240. XX    register INT    seg;
  1241. XX    register struct sc_screen    *sc;
  1242. XX    register struct    li_line        *line, *newline;
  1243. XX    INT      linewidth;
  1244. XX    static     INT    prev_column;
  1245.  
  1246. XX    errflag = 0;
  1247. XX    sc = &screen;
  1248. XX    newline = sc->sc_curline + (lineno - sc->sc_lineno);
  1249. XX    /*
  1250. XX     * Boundary checks
  1251. XX     */
  1252. XX    if (newline < sc->sc_topline || newline > sc->sc_botline) {
  1253. XX        errflag = 1;
  1254. XX        botprint(TRUE,"move_cursor, lineno %d beyond screen\n", lineno);
  1255. XX        return;
  1256. XX    }
  1257.  
  1258. XX    if (column == COL_SAME)
  1259. XX        column = file_column(newline->li_text, prev_column);
  1260. XX    else {
  1261. XX        prev_column = -1;
  1262. XX        if (column == COL_FIRST_NONWHITE) {
  1263. XX            register char *s;
  1264.  
  1265. XX            s = newline->li_text;
  1266. XX            while (*s != '\0' && isspace(*s))
  1267. XX                ++s;
  1268. XX            column = s - newline->li_text;
  1269. XX        }
  1270. XX    }
  1271.  
  1272. XX                
  1273. XX    if (column < 0) { /* If past left side of screen */
  1274. XX        if (sc->sc_column == 0) { /* Already at left side? */
  1275. XX            errflag = 1;
  1276. XX            flash();
  1277. XX            return;
  1278. XX        }
  1279. XX        column = 0;
  1280. XX    }
  1281.  
  1282. XX    if (lineno != sc->sc_lineno && sc->sc_origline.li_text != NULL)
  1283. XX        xmit_curline();
  1284.  
  1285. XX    /*
  1286. XX     * Compute screen column and segment #
  1287. XX     */
  1288. XX    sc->sc_curline = newline;
  1289. XX    sc->sc_lineno = lineno;
  1290. XX    /*
  1291. XX     * Limit column to end of line (or line+1 if input mode)
  1292. XX     */
  1293. XX    linewidth = newline->li_width + (input_mode ? 1 : 0);
  1294. XX    if (column >= linewidth && column > 0) {
  1295. XX        column = (linewidth == 0 ? 0 : linewidth-1);
  1296. XX        if (sc->sc_column >= column) /* If already at edge */
  1297. XX            flash();
  1298. XX    }
  1299.  
  1300. XX    sc->sc_column = column;
  1301. XX    column = screen_column(newline->li_text, column);
  1302. XX    if (prev_column < 0)
  1303. XX        prev_column = column;
  1304. XX    if (input_mode && sc->sc_column == linewidth-1 && sc->sc_column != 0)
  1305. XX        ++column;
  1306.  
  1307. XX    seg = 0;
  1308. XX    for (line=sc->sc_topline; line < newline; ++line)
  1309. XX        seg += line->li_segments;
  1310. XX    seg += column / COLS + sc->sc_abovetop;
  1311. XX    column %= COLS;
  1312. XX    if (seg >= LINES) {
  1313. XX        errflag = 1;
  1314. XX        botprint(TRUE, "move_cursor, seg %d beyond screen\n", seg);
  1315. XX        return;
  1316. XX    }
  1317. XX    /*
  1318. XX     * Update cursor to curses
  1319. XX     */
  1320. XX    move(seg, column);
  1321. XX}
  1322. @//E*O*F rv_move.c//
  1323. chmod u=rw,g=rw,o=rw $OUT
  1324.  
  1325. echo x - rv_openline.c
  1326. if test -f rv_openline.c ; then
  1327.     echo rv_openline.c exists, putting output in $$rv_openline.c
  1328.     OUT=$$rv_openline.c
  1329.     STATUS=1
  1330. else
  1331.     OUT=rv_openline.c
  1332. fi
  1333. sed 's/^XX//' > $OUT <<'@//E*O*F rv_openline.c//'
  1334. XX#include "rv.h"
  1335. XX#include <ctype.h>
  1336.  
  1337. XXboolean opened_line;     /* Set TRUE if openline() called */
  1338. XXINT  autoindent;     /* Physical autoindent, used by insert() */
  1339.  
  1340. XXvoid
  1341. XXopenline(direction)
  1342. XX/*
  1343. XX *  Openline - Open new line.
  1344. XX *
  1345. XX *  If direction < 0, open above current line, else
  1346. XX *                    open below current line.
  1347. XX */
  1348. XXINT direction;
  1349. XX{
  1350. XX    register struct li_line      *line;
  1351. XX    register struct sc_screen *sc;
  1352. XX    register struct wi_window *wi;
  1353. XX    char *s;
  1354.  
  1355. XX    sc = &screen;
  1356. XX    wi = &window;
  1357.  
  1358. XX    file.fi_modified = TRUE;
  1359. XX    xmit_curline();
  1360. XX    opened_line = TRUE;
  1361.  
  1362. XX    /*
  1363. XX     * Calculate autoindent
  1364. XX     */
  1365. XX    autoindent = 0;
  1366. XX    if (set_autoindent) {
  1367. XX        s = sc->sc_curline->li_text;
  1368. XX        while (isspace(*s) && *s != '\0')
  1369. XX            if (*s++ == '\t')
  1370. XX                autoindent += set_tabstops;
  1371. XX            else
  1372. XX                autoindent++;
  1373. XX    }
  1374.  
  1375. XX    /*
  1376. XX     * Send blank line to ed
  1377. XX     */
  1378. XX    if (direction >= 0) {
  1379. XX        xmit_ed("%da\n\n.\n", sc->sc_lineno);
  1380. XX        sc->sc_lineno++;
  1381. XX        sc->sc_curline++;
  1382. XX    } else
  1383. XX        xmit_ed("%di\n\n.\n", sc->sc_lineno);
  1384.  
  1385. XX    if (sc->sc_curline <= wi->wi_botline ||
  1386. XX            wi->wi_botline < &line_array[NUM_WINDOW_LINES-1]) {
  1387. XX        /*
  1388. XX         * Case 1,2,3:  Opening line at top of window, within window,
  1389. XX         *              or bottom of expandable window
  1390. XX         */
  1391.  
  1392. XX        /*
  1393. XX         * Scroll off bottom line of window if necessary
  1394. XX         */
  1395. XX        if (wi->wi_botline >= &line_array[NUM_WINDOW_LINES-1]) {
  1396. XX            if (wi->wi_botline->li_text)
  1397. XX                free(wi->wi_botline->li_text);
  1398. XX            wi->wi_botline->li_text = NULL;
  1399. XX            wi->wi_botline--;
  1400. XX        }
  1401.  
  1402. XX        /*
  1403. XX         * Slide down window beyond line
  1404. XX         */
  1405. XX        for (line = wi->wi_botline; line >= sc->sc_curline; --line) {
  1406. XX            (line+1)->li_width = line->li_width;
  1407. XX            (line+1)->li_segments = line->li_segments;
  1408. XX            (line+1)->li_text = line->li_text;
  1409. XX        }
  1410. XX        wi->wi_botline++;
  1411. XX    } else {
  1412. XX        /*
  1413. XX         * Case 4: Opening line beyond edge of unexpandable window
  1414. XX         */
  1415.  
  1416. XX        sc->sc_curline--;
  1417. XX        /*
  1418. XX         * Scroll off topline of window if necessary
  1419. XX         */
  1420. XX        if (wi->wi_topline <= &line_array[0]) {
  1421. XX            if (wi->wi_topline->li_text)
  1422. XX                free(wi->wi_topline->li_text);
  1423. XX            wi->wi_topline->li_text = NULL;
  1424. XX            wi->wi_topline++;
  1425. XX        }
  1426.  
  1427. XX        /*
  1428. XX         * Slide up window
  1429. XX         */
  1430. XX        for (line = wi->wi_topline; line < sc->sc_curline; ++line) {
  1431. XX            (line-1)->li_width = line->li_width;
  1432. XX            (line-1)->li_segments = line->li_segments;
  1433. XX            (line-1)->li_text = line->li_text;
  1434. XX        }
  1435. XX        wi->wi_topline--;
  1436. XX        sc->sc_topline--;
  1437. XX        sc->sc_botline--;
  1438. XX    }
  1439.  
  1440. XX    /*
  1441. XX     * Create the empty line
  1442. XX     */
  1443. XX    line = sc->sc_curline;
  1444. XX    line->li_width = 0;
  1445. XX    line->li_segments = 1;
  1446. XX    line->li_text = xalloc(1);
  1447. XX    line->li_text[0] = '\0';
  1448.  
  1449. XX    if (line > wi->wi_botline)
  1450. XX        wi->wi_botline = line;
  1451.  
  1452. XX    file.fi_numlines++;
  1453.  
  1454. XX    /*
  1455. XX     * Set up for insert()
  1456. XX     */
  1457. XX    sc->sc_firstcol = 0;
  1458. XX    sc->sc_lastcol = -1;
  1459.  
  1460. XX    /*
  1461. XX     * Remember opened line for later undo
  1462. XX     */
  1463. XX    undo.un_validcol = FALSE;
  1464. XX    undo.un_firstline = sc->sc_lineno;
  1465. XX    undo.un_lastline = sc->sc_lineno;
  1466. XX    undo.un_inserted = TRUE;
  1467.  
  1468. XX    /*
  1469. XX     * Update line to curses
  1470. XX     */
  1471. XX    if (line > sc->sc_botline) {
  1472. XX        redraw_screen(sc->sc_botline+1);
  1473. XX        move_cursor(sc->sc_lineno, 0);
  1474. XX    } else {
  1475. XX        move_cursor(sc->sc_lineno, 0);
  1476. XX        rv_finsertln(1);
  1477. XX        redraw_screen(sc->sc_botline);
  1478. XX    }
  1479. XX}
  1480. @//E*O*F rv_openline.c//
  1481. chmod u=rw,g=rw,o=rw $OUT
  1482.  
  1483. echo x - rv_put.c
  1484. if test -f rv_put.c ; then
  1485.     echo rv_put.c exists, putting output in $$rv_put.c
  1486.     OUT=$$rv_put.c
  1487.     STATUS=1
  1488. else
  1489.     OUT=rv_put.c
  1490. fi
  1491. sed 's/^XX//' > $OUT <<'@//E*O*F rv_put.c//'
  1492. XX#include "rv.h"
  1493.  
  1494. XXextern char *realloc();
  1495.  
  1496. XXvoid
  1497. XXput(direction)
  1498. XX/*
  1499. XX * Put buffer at cursor.
  1500. XX */
  1501. XXINT direction; /* Negative if above cursor */
  1502. XX{
  1503. XX    register struct li_line      *line;
  1504. XX    register struct ya_yank   *yank;
  1505. XX    register struct sc_screen *sc;
  1506. XX    INT    indx;
  1507.  
  1508. XX    sc = &screen;
  1509. XX    line = sc->sc_curline;
  1510.  
  1511. XX    indx = char_to_yank(yank_cmd);
  1512. XX    if (errflag) {
  1513. XX        flash();
  1514. XX        return;
  1515. XX    }
  1516. XX    yank = &yank_array[indx];
  1517.  
  1518. XX    file.fi_modified = TRUE;
  1519. XX    if (yank->ya_type == YANK_EMPTY) {
  1520. XX        errflag = 1;
  1521. XX        if (yank_cmd == ' ')
  1522. XX            flash();
  1523. XX        else 
  1524. XX            botprint(TRUE, "Register %c is empty", yank_cmd);
  1525. XX        return;
  1526. XX    }
  1527. XX    undo.un_inserted = TRUE;
  1528. XX    undo.un_firstline = undo.un_lastline = sc->sc_lineno;
  1529. XX    undo.un_validcol = FALSE;
  1530. XX    if (yank->ya_type == YANK_COLS) {
  1531. XX        /*
  1532. XX         * Put text within line
  1533. XX         */
  1534. XX        register char *s, *s2, *s3;
  1535.  
  1536. XX        save_Undo();
  1537. XX        undo.un_validcol = sc->sc_validcol = TRUE;
  1538. XX        undo.un_firstcol = sc->sc_firstcol = sc->sc_column+1;
  1539. XX        undo.un_lastcol = sc->sc_lastcol = sc->sc_column+yank->ya_width;
  1540. XX        line->li_text = realloc(line->li_text, line->li_width +
  1541. XX            yank->ya_width + 1);
  1542. XX        s = &line->li_text[sc->sc_firstcol];
  1543. XX        s2 = &line->li_text[line->li_width];
  1544. XX        s3 = &line->li_text[line->li_width + yank->ya_width];
  1545. XX        while (s2 >= s)
  1546. XX            *s3-- = *s2--;
  1547. XX        s2 = yank->ya_text;
  1548. XX        while (*s2)
  1549. XX            *s++ = *s2++;
  1550. XX        redraw_curline(line->li_text);
  1551. XX        move_cursor(sc->sc_lineno, sc->sc_firstcol + yank->ya_width-1);
  1552. XX        if (set_fortran && line->li_width > 72) {
  1553. XX            botprint(FALSE, "Line is longer than 72 columns");
  1554. XX            hitcr_continue();
  1555. XX        }
  1556. XX    }
  1557. XX    else { /* Put text between lines */
  1558. XX        sc->sc_validcol = FALSE;
  1559. XX        if (yank->ya_type == YANK_SINGLE) {
  1560. XX            /*
  1561. XX             * Simple case - put 1 line
  1562. XX             */
  1563. XX            openline(direction);
  1564. XX            save_Undo();
  1565. XX            redraw_curline(yank->ya_text);
  1566. XX            move_cursor(sc->sc_lineno, COL_FIRST_NONWHITE);
  1567. XX        }
  1568. XX        else {
  1569. XX            /*
  1570. XX             * put multiple lines
  1571. XX             */
  1572. XX            xmit_curline();
  1573. XX            xmit_ed("%dr /tmp/yk%d.%d\n", sc->sc_lineno -
  1574. XX                (direction >= 0 ? 0 : 1), getpid(), indx);
  1575. XX            undo.un_lastline = sc->sc_lineno + yank->ya_numlines-1;
  1576. XX            fetch_window(sc->sc_lineno - NUM_WINDOW_LINES/4 -
  1577. XX                LINES/2 + 1, TRUE);
  1578. XX            botprint(FALSE, "%d more lines", yank->ya_numlines);
  1579. XX            hitcr_continue();
  1580. XX        }
  1581. XX    }
  1582. XX}
  1583. @//E*O*F rv_put.c//
  1584. chmod u=rw,g=rw,o=rw $OUT
  1585.  
  1586. echo x - rv_redraw.c
  1587. if test -f rv_redraw.c ; then
  1588.     echo rv_redraw.c exists, putting output in $$rv_redraw.c
  1589.     OUT=$$rv_redraw.c
  1590.     STATUS=1
  1591. else
  1592.     OUT=rv_redraw.c
  1593. fi
  1594. sed 's/^XX//' > $OUT <<'@//E*O*F rv_redraw.c//'
  1595. XX#include "rv.h"
  1596.  
  1597. XXvoid
  1598. XXredraw_screen(firstline)
  1599. XX/*
  1600. XX * Regenerate the screen from firstline downwards to curses
  1601. XX *
  1602. XX * If firstline is NULL, the entire screen is redrawn.
  1603. XX */
  1604. XXstruct    li_line    *firstline;
  1605. XX{
  1606. XX    register struct   li_line    *line;
  1607. XX    register struct     sc_screen    *sc;
  1608. XX    register struct     wi_window    *wi;
  1609. XX    INT     saveline, savecol, seg;
  1610.  
  1611. XX    sc = &screen;
  1612. XX    wi = &window;
  1613. XX    if (firstline == (struct li_line *)0)
  1614. XX        firstline = sc->sc_topline;
  1615. XX    /*
  1616. XX     * Save cursor location
  1617. XX     */
  1618. XX    saveline = CURLINE;
  1619. XX    savecol = CURCOLUMN;
  1620. XX    /*
  1621. XX     * Skip void line segments above topline
  1622. XX     */
  1623. XX    if (firstline == sc->sc_topline) {
  1624. XX        sc->sc_abovetop = 0; /* Reset topline to real screen top */
  1625. XX        seg = 0;
  1626. XX    } else
  1627. XX        seg = sc->sc_abovetop;
  1628. XX    /*
  1629. XX     * Skip lines above firstline
  1630. XX     */
  1631. XX    for (line=sc->sc_topline; line < firstline; ++line)
  1632. XX        seg += line->li_segments;
  1633. XX    /*
  1634. XX     * Clear screen from firstline downward
  1635. XX     */
  1636. XX    move(seg,0);
  1637. XX    clrtobot();
  1638. XX    move(seg,0);  /* Because clrtobot homes the cursor in 4bsd */
  1639.  
  1640. XX    /*
  1641. XX     * Redraw remaining lines
  1642. XX     */
  1643. XX    if (line <= wi->wi_botline)
  1644. XX        seg += line->li_segments;
  1645. XX    if (seg >= LINES && sc->sc_curline == line) {
  1646. XX        /*
  1647. XX         * Scroll
  1648. XX         */
  1649. XX        sc->sc_botline = line-1;
  1650. XX        rv_scroll(1);
  1651. XX        redraw_screen(line+1);
  1652. XX        move(saveline, savecol);
  1653. XX        return;
  1654. XX    }
  1655. XX        
  1656. XX    while (seg < LINES) {
  1657. XX        if (line <= wi->wi_botline) {
  1658. XX            print_line(line->li_text);
  1659. XX            if (CURCOLUMN != 0 || line->li_text[0] == '\0')
  1660. XX                move(CURLINE+1, 0);
  1661. XX            ++line;
  1662. XX        }
  1663. XX        if (line > wi->wi_botline) { /* If past bottom of window */
  1664. XX            if ((line - sc->sc_curline) + sc->sc_lineno >
  1665. XX                    file.fi_numlines) /* If past eof */
  1666. XX                break;
  1667. XX            /*
  1668. XX             * Fetch window & redraw everything
  1669. XX             */
  1670. XX             if (set_debug > 1)
  1671. XX                 fprintf(stderr, "Forced to redraw\n");
  1672. XX                 fetch_window(sc->sc_lineno - NUM_WINDOW_LINES/4 -
  1673. XX                 LINES/2+1, TRUE);
  1674. XX                 return;
  1675. XX        }
  1676. XX        seg += line->li_segments;
  1677. XX    }
  1678. XX    sc->sc_botline = line-1;
  1679.  
  1680. XX    /*
  1681. XX     * Append '~' or '@' lines to screen
  1682. XX     */
  1683. XX    if ((seg = CURLINE) < LINES-1) 
  1684. XX        if (file.fi_numlines > sc->sc_lineno +
  1685. XX                (sc->sc_botline - sc->sc_curline))
  1686. XX            /*
  1687. XX             * Undisplayed lines
  1688. XX             */
  1689. XX            while (seg < LINES-1)
  1690. XX                mvaddch(seg++, 0, '@');
  1691. XX        else
  1692. XX            /*
  1693. XX             * End of file
  1694. XX             */
  1695. XX            while (seg < LINES-1)
  1696. XX                mvaddch(seg++, 0, '~');
  1697. XX    /*
  1698. XX     * Restore cursor
  1699. XX     */
  1700. XX    move(saveline, savecol);
  1701. XX}
  1702. @//E*O*F rv_redraw.c//
  1703. chmod u=rw,g=rw,o=rw $OUT
  1704.  
  1705. echo x - rv_redraw_ln.c
  1706. if test -f rv_redraw_ln.c ; then
  1707.     echo rv_redraw_ln.c exists, putting output in $$rv_redraw_ln.c
  1708.     OUT=$$rv_redraw_ln.c
  1709.     STATUS=1
  1710. else
  1711.     OUT=rv_redraw_ln.c
  1712. fi
  1713. sed 's/^XX//' > $OUT <<'@//E*O*F rv_redraw_ln.c//'
  1714. XX#include "rv.h"
  1715.  
  1716. XXvoid
  1717. XXredraw_curline(txt)
  1718. XX/*
  1719. XX * Redraw the current line using txt.
  1720. XX * Update rest of screen as necessary
  1721. XX */
  1722. XXchar *txt;
  1723. XX{
  1724. XX    register struct li_line      *line;
  1725. XX    register struct li_line    *line2;
  1726. XX    register struct sc_screen *sc;
  1727. XX    register INT    seg, i;
  1728. XX    char    *oldtxt;
  1729.  
  1730. XX    sc = &screen;
  1731. XX    line = sc->sc_curline;
  1732. XX    seg = line->li_segments;
  1733. XX    oldtxt = line->li_text;
  1734.  
  1735. XX    /*
  1736. XX     * Rebuild line internally
  1737. XX     */
  1738. XX    line->li_width = strlen(txt);
  1739. XX    line->li_segments = 1 + (screen_column(txt, line->li_width-1) +
  1740. XX        set_list) / COLS;
  1741. XX    if (line->li_text != txt) {
  1742. XX        line->li_text = xalloc(line->li_width+1);
  1743. XX        strcpy(line->li_text, txt);
  1744. XX        if (oldtxt)
  1745. XX            free(oldtxt);
  1746. XX    }
  1747.  
  1748. XX    i = sc->sc_abovetop;
  1749. XX    for (line = sc->sc_topline; line < sc->sc_curline; ++line)
  1750. XX        i += line->li_segments;
  1751. XX    move(i, 0);
  1752.  
  1753. XX    if (CURLINE+line->li_segments >= LINES) {
  1754. XX        /*
  1755. XX         * Line overflowed screen
  1756. XX         */
  1757. XX        redraw_screen(line);
  1758. XX        return;
  1759. XX    }
  1760.  
  1761. XX    /*
  1762. XX     * If grew, push down segs below this line
  1763. XX     */
  1764. XX    if (line->li_segments > seg) {
  1765. XX        i = line->li_segments - seg;
  1766. XX        rv_finsertln(i);
  1767. XX        /* Redraw pushed off segs */
  1768. XX        i = line->li_segments - seg;
  1769. XX        line2 = sc->sc_botline;
  1770. XX        while (i >= 0) {
  1771. XX            i -= line2->li_segments;
  1772. XX            --line2;
  1773. XX        }
  1774. XX        if (line2 <= line)
  1775. XX            line2 = line + 1;
  1776. XX        redraw_screen(line2);
  1777. XX    }
  1778.  
  1779. XX    /*
  1780. XX     * Clear segments and redraw
  1781. XX     */
  1782. XX    clrtoeol();
  1783. XX    for (i=line->li_segments; i > 1; --i) {
  1784. XX        move(CURLINE+1, 0);
  1785. XX        clrtoeol();
  1786. XX    }
  1787. XX    /*
  1788. XX     * Move to first seg of line
  1789. XX     */
  1790. XX    if (line->li_segments > 1)
  1791. XX        move(CURLINE-line->li_segments+1, 0);
  1792.  
  1793. XX    /*
  1794. XX     * Draw line
  1795. XX     */
  1796. XX    i = CURLINE;
  1797. XX    print_line(line->li_text);
  1798. XX    if (seg <= line->li_segments)
  1799. XX        return;
  1800.  
  1801. XX    /*
  1802. XX     * Shrunk, delete surplus segs
  1803. XX     */
  1804. XX    move(i+line->li_segments, 0);
  1805. XX    i = seg - line->li_segments;
  1806. XX    rv_fdeleteln(i);
  1807. XX    redraw_screen(sc->sc_botline+1);
  1808. XX}
  1809. @//E*O*F rv_redraw_ln.c//
  1810. chmod u=rw,g=rw,o=rw $OUT
  1811.  
  1812. echo x - rv_scroll.c
  1813. if test -f rv_scroll.c ; then
  1814.     echo rv_scroll.c exists, putting output in $$rv_scroll.c
  1815.     OUT=$$rv_scroll.c
  1816.     STATUS=1
  1817. else
  1818.     OUT=rv_scroll.c
  1819. fi
  1820. sed 's/^XX//' > $OUT <<'@//E*O*F rv_scroll.c//'
  1821. XX#include "rv.h"
  1822.  
  1823. XXvoid
  1824. XXrv_scroll(n)
  1825. XX/*
  1826. XX * Scroll n lines
  1827. XX * Must be within window
  1828. XX * Cursor is set to last line
  1829. XX */
  1830. XXregister INT n;
  1831. XX{
  1832. XX    register struct li_line   *line, *oldline;
  1833. XX    register struct sc_screen *sc;
  1834. XX    register INT    seg,newseg,i;
  1835. XX    register struct wi_window *wi;
  1836.  
  1837. XX    sc = &screen;
  1838. XX    wi = &window;
  1839. XX    /*
  1840. XX     * Set cursor to bottom line+1
  1841. XX     */
  1842. XX    newseg = 0;
  1843. XX    for (line = sc->sc_topline; line <= sc->sc_botline; ++line)
  1844. XX        newseg += line->li_segments;
  1845. XX    newseg += sc->sc_abovetop;
  1846. XX    move(newseg,0);
  1847. XX    clrtobot();
  1848. XX    /*
  1849. XX     * Calculate number of segments to scroll in
  1850. XX     */
  1851. XX    seg = 0;
  1852. XX    for (i=n; i > 0 && line <= wi->wi_botline; --i, ++line)
  1853. XX        seg += line->li_segments;
  1854. XX    seg -= LINES-newseg-1;
  1855. XX    move(LINES-1,0);
  1856. XX    rv_fscroll(seg);
  1857. XX    move(newseg-seg,0);
  1858. XX    /*
  1859. XX     * Scroll in new line(s)
  1860. XX     */
  1861. XX    for (line = sc->sc_botline+1; n > 0; --n, ++line) {
  1862. XX        if (line > wi->wi_botline) {
  1863. XX            errflag = 1;
  1864. XX            botprint(TRUE, "rv_scroll - past bottom of window\n\n");
  1865. XX            hitcr_continue();
  1866. XX            return;
  1867. XX        }
  1868. XX        print_line(line->li_text);
  1869. XX        if (CURCOLUMN != 0 || line->li_text[0] == '\0') {
  1870. XX            if (CURLINE == LINES-1) {
  1871. XX                move(LINES-1, 0);
  1872. XX            } else
  1873. XX                move(CURLINE+1, 0);
  1874. XX        }
  1875. XX    }
  1876. XX    /*
  1877. XX     * Adjust screen params
  1878. XX     */
  1879. XX    xmit_curline();
  1880. XX    --line;
  1881. XX    sc->sc_lineno += (line - sc->sc_curline);
  1882. XX    sc->sc_botline = line;
  1883. XX    sc->sc_curline = line;
  1884. XX    sc->sc_column = 0;
  1885.  
  1886. XX    /*
  1887. XX     * Compute new top line
  1888. XX     */
  1889. XX    for (seg = line->li_segments; seg < LINES;
  1890. XX            seg += line->li_segments) {
  1891. XX        --line;
  1892. XX        if (line < wi->wi_topline)
  1893. XX            break;
  1894. XX    }
  1895. XX    sc->sc_topline = line+1;
  1896. XX    /*
  1897. XX     * Compute # of displayed segs above top line
  1898. XX     */
  1899. XX    if (line >= wi->wi_topline)
  1900. XX        sc->sc_abovetop = LINES-1 - (seg - line->li_segments);
  1901. XX}
  1902. @//E*O*F rv_scroll.c//
  1903. chmod u=rw,g=rw,o=rw $OUT
  1904.  
  1905. echo x - rv_scroll_bk.c
  1906. if test -f rv_scroll_bk.c ; then
  1907.     echo rv_scroll_bk.c exists, putting output in $$rv_scroll_bk.c
  1908.     OUT=$$rv_scroll_bk.c
  1909.     STATUS=1
  1910. else
  1911.     OUT=rv_scroll_bk.c
  1912. fi
  1913. sed 's/^XX//' > $OUT <<'@//E*O*F rv_scroll_bk.c//'
  1914. XX#include "rv.h"
  1915.  
  1916. XXvoid
  1917. XXrv_scroll_backward(n)
  1918. XX/*
  1919. XX * Scroll n lines backward
  1920. XX * Must be within window
  1921. XX * Cursor location is undefined
  1922. XX */
  1923. XXregister n;
  1924. XX{
  1925. XX    register struct li_line   *line, *newline;
  1926. XX    register struct sc_screen *sc;
  1927. XX    register INT    seg;
  1928. XX    register struct wi_window *wi;
  1929. XX    register struct fi_file      *fi;
  1930.  
  1931. XX    sc = &screen;
  1932. XX    wi = &window;
  1933. XX    fi = &file;
  1934. XX    seg = 0;
  1935. XX    for (line = sc->sc_topline-1; n > 0; --n, --line) {
  1936. XX        if (line < wi->wi_topline) {
  1937. XX            errflag = 1;
  1938. XX            botprint(TRUE,
  1939. XX                "rv_scroll_backward - past top of window\n\n");
  1940. XX            hitcr_continue();
  1941. XX            return;
  1942. XX        }
  1943. XX        seg += line->li_segments;
  1944. XX    }
  1945. XX    ++line;
  1946. XX    move(0,0);
  1947. XX    seg -= sc->sc_abovetop;
  1948. XX    rv_finsertln(seg);
  1949. XX    move(0,0);
  1950. XX    for (newline = line; newline < sc->sc_topline; ++newline) {
  1951. XX        print_line(newline->li_text);
  1952. XX        if (CURCOLUMN != 0 || newline->li_text[0] == '\0')
  1953. XX            move(CURLINE+1, 0);
  1954. XX    }
  1955. XX    xmit_curline();
  1956. XX    sc->sc_lineno = sc->sc_lineno - (sc->sc_curline - line);
  1957. XX    sc->sc_topline = line;
  1958. XX    sc->sc_curline = line;
  1959. XX    sc->sc_column = 0;
  1960. XX    sc->sc_abovetop = 0;
  1961.  
  1962. XX    /*
  1963. XX     * Compute bottom line
  1964. XX     */
  1965. XX    for (seg = line->li_segments; seg < LINES;
  1966. XX            seg += line->li_segments) {
  1967. XX        ++line;
  1968. XX        if (line > wi->wi_botline)
  1969. XX            break;
  1970. XX    }
  1971. XX    sc->sc_botline = line-1;
  1972.  
  1973. XX    if (line <= wi->wi_botline)
  1974. XX        seg -= line->li_segments;
  1975. XX    move(seg, 0);
  1976. XX    clrtobot();
  1977. XX    move(seg, 0); /* Because clrtobot homes the cursor in 4bsd */
  1978. XX    /*
  1979. XX     * Append '~' or '@' lines to screen
  1980. XX     */
  1981. XX    if (seg < LINES-1) 
  1982. XX        if (fi->fi_numlines > sc->sc_lineno +
  1983. XX                (sc->sc_botline - sc->sc_curline))
  1984. XX        /*
  1985. XX         * Undisplayed lines
  1986. XX         */
  1987. XX        while (seg < LINES-1)
  1988. XX            mvaddch(seg++, 0, '@');
  1989. XX    else
  1990. XX        /*
  1991. XX         * End of file
  1992. XX         */
  1993. XX        while (seg < LINES-1)
  1994. XX            mvaddch(seg++, 0, '~');
  1995. XX    move(0,0);
  1996. XX}
  1997. @//E*O*F rv_scroll_bk.c//
  1998. chmod u=rw,g=rw,o=rw $OUT
  1999.  
  2000. echo x - rv_search.c
  2001. if test -f rv_search.c ; then
  2002.     echo rv_search.c exists, putting output in $$rv_search.c
  2003.     OUT=$$rv_search.c
  2004.     STATUS=1
  2005. else
  2006.     OUT=rv_search.c
  2007. fi
  2008. sed 's/^XX//' > $OUT <<'@//E*O*F rv_search.c//'
  2009. XX#include "rv.h"
  2010. XX#include "regexp.h"
  2011.  
  2012. XX#ifdef CRAY
  2013. XX#define move_cursor_flag   mc_flag
  2014. XX#endif
  2015.  
  2016. XXstatic char prev_search[256];   /* Buffer holding previous search string */
  2017. XXstatic char buf[256];        /* Buffer holding current search string */
  2018. XXstatic regexp *cmp;        /* Compiled regular expression (RE) */
  2019.  
  2020. XXboolean
  2021. XXsearch(direction, txt, move_cursor_flag)
  2022. XX/*
  2023. XX * Search file for match
  2024. XX *
  2025. XX * Scan current line using regexec() for txt
  2026. XX * If not found, xmit search request to ed
  2027. XX *      Scan line that ed finds using regex()
  2028. XX * Put cursor at new location, if move_cursor_flag
  2029. XX */
  2030. XXINT  direction;   /* Direction of search (-1, 1) */
  2031. XXchar *txt;        /* Regular expression to search for */
  2032. XXboolean move_cursor_flag; /* TRUE if cursor to be moved to match */
  2033. XX{
  2034. XX    register struct sc_screen *sc;
  2035. XX    register char *s, *s2;
  2036. XX    register INT i, ch;
  2037. XX    struct li_line   *line;
  2038. XX    INT offset = 0;
  2039. XX    char *found, numbuf[20];
  2040.  
  2041. XX    sc = &screen;
  2042. XX    sc->sc_validcol = TRUE;
  2043. XX    sc->sc_firstcol = sc->sc_lastcol = sc->sc_column;
  2044. XX    sc->sc_firstline = sc->sc_lastline = sc->sc_lineno;
  2045.  
  2046. XX    if (txt == NULL)
  2047. XX        return FALSE;
  2048. XX    strcpy(buf, txt);
  2049. XX    if (direction >= 0)
  2050. XX        ch = '/';
  2051. XX    else
  2052. XX        ch = '?';
  2053. XX    s = buf;
  2054. XX    /*
  2055. XX     * Scan for first / or ? not preceeded by an odd number of backslashes
  2056. XX     */
  2057. XX    i = 0;
  2058. XX    while (*s != '\0' && (*s != ch || i & 1)) {
  2059. XX        i = *s == '\\' ? i+1 : 0;
  2060. XX        ++s;
  2061. XX    }
  2062. XX    /*
  2063. XX     * Drop '\0' into matching / or ?
  2064. XX     */
  2065. XX    if (*s != '\0')
  2066. XX        *s++ = '\0';
  2067. XX    ch = *s;
  2068.  
  2069. XX    /*
  2070. XX     * Check for +/- offset
  2071. XX     */
  2072. XX    if (ch == '+' || ch == '-') {
  2073. XX        offset = atoi(s);
  2074. XX        if (offset == 0 && *(s+1) != '0')
  2075. XX            offset = 1;
  2076. XX        if (*s == '-')
  2077. XX            offset = -offset;
  2078. XX        sc->sc_validcol = FALSE;
  2079. XX    }
  2080.  
  2081. XX    if (*buf == '\0')
  2082. XX        strcpy(buf, prev_search);
  2083. XX    if (*buf == '\0') {
  2084. XX        botprint(TRUE, "No remembered search string");
  2085. XX        return FALSE;
  2086. XX    }
  2087. XX    /*
  2088. XX     * Compile RE
  2089. XX     */
  2090. XX    if (cmp)
  2091. XX        free(cmp);
  2092. XX    if ((cmp = regcomp(buf)) == 0) {
  2093. XX        return FALSE;
  2094. XX    }
  2095.  
  2096. XX    strcpy(prev_search, buf);
  2097.  
  2098. XX    line = sc->sc_curline;
  2099. XX    s = &line->li_text[sc->sc_column];
  2100. XX    found = NULL;
  2101. XX    if (direction >= 0) {
  2102. XX        /*
  2103. XX         * Search current line after cursor 
  2104. XX         */
  2105. XX        if (*buf != '^' && *++s != '\0')
  2106. XX            if (regexec(cmp, s) != 0) {
  2107. XX                found = cmp->startp[0];
  2108. XX                sc->sc_lastcol = found - line->li_text - 1;
  2109. XX            }
  2110. XX    } else {
  2111. XX        /*
  2112. XX         * Search current line before cursor
  2113. XX         */
  2114. XX        s2 = line->li_text;
  2115. XX        while (s2 < s) {
  2116. XX            if (regexec(cmp, s2) == 0 || cmp->startp[0] >= s)
  2117. XX                break;
  2118. XX            found = cmp->startp[0];
  2119. XX            if (*buf == '^') /* If anchored */
  2120. XX                break;
  2121. XX            s2 = cmp->startp[0]+1;
  2122. XX        }
  2123. XX        if (found) {
  2124. XX            sc->sc_lastcol--;
  2125. XX            sc->sc_firstcol = found - line->li_text;
  2126. XX        }
  2127. XX    }
  2128.  
  2129. XX    if (found) {
  2130. XX        /*
  2131. XX         * Found match on current line
  2132. XX         */
  2133. XX         if (offset != 0) {
  2134. XX            /*
  2135. XX             * Line offset requested from current line (sigh)
  2136. XX             */
  2137. XX            sc->sc_validcol = FALSE;
  2138. XX            if ((i = sc->sc_lineno + offset) < 1) {
  2139. XX                botprint(TRUE, "Negative address");
  2140. XX                return FALSE;
  2141. XX            }
  2142. XX            if (i > file.fi_numlines) {
  2143. XX                botprint(TRUE, "Not that many lines in buffer");
  2144. XX                return FALSE;
  2145. XX            }
  2146. XX            if (i < sc->sc_lineno)
  2147. XX                sc->sc_firstline = i;
  2148. XX            else if (i > sc->sc_lineno)
  2149. XX                sc->sc_lastline = i-1;
  2150. XX            if (move_cursor_flag)
  2151. XX                move_abs_cursor(i, COL_FIRST_NONWHITE);
  2152. XX            return TRUE;
  2153. XX        }
  2154. XX        if (move_cursor_flag)
  2155. XX            if (sc->sc_firstcol != sc->sc_column)
  2156. XX                move_cursor(sc->sc_lineno, sc->sc_firstcol);
  2157. XX            else
  2158. XX                move_cursor(sc->sc_lineno, sc->sc_lastcol+1);
  2159. XX        return TRUE;
  2160. XX        }
  2161.  
  2162. XX    sc->sc_validcol = FALSE;
  2163. XX    /*
  2164. XX     * Xmit search to ed
  2165. XX     */
  2166. XX    xmit_curline();
  2167. XX    i = sc->sc_lineno;
  2168. XX    if (direction >= 0)
  2169. XX        xmit_ed("%d\n/%s/\n", i, buf);
  2170. XX    else
  2171. XX        xmit_ed("%d\n?%s?\n", i, buf);
  2172. XX    xmit_sync();
  2173. XX    xmit_ed(".=\n");
  2174. XX    (void) recv_sync(FALSE);
  2175. XX    (void) fgets(numbuf, 18, file.fi_fpin);
  2176. XX    if ((i = atoi(numbuf)) == sc->sc_lineno) {
  2177. XX        botprint(TRUE, "Pattern not found");
  2178. XX        return FALSE;
  2179. XX    }
  2180. XX    if (set_wrapscan == FALSE && 
  2181. XX        ((direction > 0 && i < sc->sc_lineno) ||
  2182. XX         (direction < 0 && i > sc->sc_lineno))) { /* If wrapped */
  2183. XX        botprint(TRUE, "Address search hit %s without matching pattern",
  2184. XX            direction < 0 ? "TOP" : "BOTTOM");
  2185. XX        return FALSE;
  2186. XX    }
  2187. XX        
  2188. XX    i += offset;
  2189.  
  2190. XX    if (i < 1) {
  2191. XX        botprint(TRUE, "Negative address");
  2192. XX        return FALSE;
  2193. XX    }
  2194. XX    if (i > file.fi_numlines) {
  2195. XX        botprint(TRUE, "Not that many lines in buffer");
  2196. XX        return FALSE;
  2197. XX    }
  2198.  
  2199. XX    if (i < sc->sc_lineno)
  2200. XX        sc->sc_firstline = i;
  2201. XX    else if (i > sc->sc_lineno)
  2202. XX        sc->sc_lastline = i-1;
  2203. XX    if (!move_cursor_flag)
  2204. XX        return TRUE;
  2205. XX        
  2206. XX    /*
  2207. XX     * Cursor movement requested
  2208. XX     */
  2209.  
  2210. XX    /*
  2211. XX     * Move to line,col of match
  2212. XX     */
  2213. XX    if (offset != 0) {
  2214. XX        move_abs_cursor(i, COL_FIRST_NONWHITE);
  2215. XX        return TRUE;
  2216. XX    }
  2217. XX    move_abs_cursor(i, 0);
  2218. XX    line = sc->sc_curline;
  2219. XX    if (direction >= 0) {
  2220. XX        if (regexec(cmp, line->li_text) != 0)
  2221. XX            sc->sc_column = cmp->startp[0] - line->li_text;
  2222. XX    } else {
  2223. XX        s2 = line->li_text;
  2224. XX        found = NULL;
  2225. XX        while (*s2 != '\0') {
  2226. XX            if (regexec(cmp, s2) == 0)
  2227. XX                break;
  2228. XX            found = cmp->startp[0];
  2229. XX            if (*buf == '^') /* If anchored */
  2230. XX                break;
  2231. XX            s2 = cmp->startp[0]+1;
  2232. XX        }
  2233. XX        if (found)
  2234. XX            sc->sc_column = found - line->li_text;
  2235. XX    }
  2236. XX    move_cursor(sc->sc_lineno, sc->sc_column);
  2237. XX    return TRUE;
  2238. XX}
  2239. @//E*O*F rv_search.c//
  2240. chmod u=rw,g=rw,o=rw $OUT
  2241.  
  2242. echo x - rv_shell.c
  2243. if test -f rv_shell.c ; then
  2244.     echo rv_shell.c exists, putting output in $$rv_shell.c
  2245.     OUT=$$rv_shell.c
  2246.     STATUS=1
  2247. else
  2248.     OUT=rv_shell.c
  2249. fi
  2250. sed 's/^XX//' > $OUT <<'@//E*O*F rv_shell.c//'
  2251. XX#include "rv.h"
  2252. XX#include <signal.h>
  2253.  
  2254. XX#ifndef USG
  2255. XX#  define strchr index
  2256. XX#endif
  2257.  
  2258. XX/*
  2259. XX * This entire module is a hack
  2260. XX */
  2261.  
  2262. XXextern boolean    scrolled;
  2263.  
  2264. XXextern char *strchr();
  2265.  
  2266. XXrv_shell(cmd)
  2267. XXchar *cmd;
  2268. XX{
  2269. XX    INT cpid, len, infd, outfd;
  2270. XX    char buf[513], *s;
  2271. XX    int (*prev_func)();
  2272. XX#ifdef USG
  2273. XX    struct termio tm;
  2274. XX#endif
  2275. XX    
  2276. XX    xmit_sync();
  2277. XX    (void) recv_sync(FALSE);
  2278. XX    xmit_ed("!sh -c '%s' ; echo '@''$''#'\n", cmd);
  2279. XX    fflush(file.fi_fpout);
  2280. XX    if (file.fi_modified)
  2281. XX        botprint(FALSE, "[No write since last change]");
  2282. XX    move(LINES-1, 0);
  2283. XX    rv_fscroll(1);
  2284. XX    move(LINES-1, 0);
  2285. XX    refresh();
  2286.  
  2287. XX    /* prev_func = signal(SIGINT, SIG_IGN);  Use at your own risk */
  2288. XX    if (use_linemode) {
  2289. XX#ifdef USG
  2290. XX        nocbreak();
  2291. XX#else
  2292. XX        nocrmode();
  2293. XX#endif
  2294. XX        nl();
  2295. XX        echo();
  2296. XX#ifdef TCGETA             /* Echo doesn't in System V, sigh */
  2297. XX        ioctl(0, TCGETA, &tm);
  2298. XX        tm.c_lflag |= ECHO;
  2299. XX        ioctl(0, TCSETA, &tm);
  2300. XX#endif
  2301. XX        if (set_debug > 2)
  2302. XX            printf("Using line mode.\n");
  2303. XX    }
  2304. XX    infd = atoi(Argv[1]);
  2305. XX    outfd = atoi(Argv[2]);
  2306. XX    if ((cpid = fork()) < 0)
  2307. XX        panic("Can't fork");
  2308. XX    if (cpid == 0) { /* Child */
  2309. XX        for (;;) {
  2310. XX            if ((len = read(0, buf, 512)) < 0)
  2311. XX                _exit(0);
  2312. XX            if (len == 0)
  2313. XX                write(outfd, "\004\n", 2);
  2314. XX            else
  2315. XX                write(outfd, buf, len);
  2316. XX        }
  2317. XX        /*NOTREACHED*/
  2318. XX    }
  2319. XX    for (;;) { /*  Parent */
  2320. XX        if ((len = read(infd, buf, 512)) <= 0)
  2321. XX            panic("EOF on read from pipe");
  2322. XX        if ((s = strchr(buf, '@')) != NULL) {
  2323. XX            if (s-buf+1 >= len) {
  2324. XX                write(1, buf, len);
  2325. XX                len = read(infd, buf, 512);
  2326. XX                s = buf;
  2327. XX            }
  2328. XX            if (*++s == '$') {
  2329. XX                if (s-buf+1 >= len) { 
  2330. XX                    write(1, buf, len);
  2331. XX                    len = read(infd, buf, 512);
  2332. XX                    s = buf;
  2333. XX                }
  2334. XX                if (*++s == '#') {
  2335. XX                    if (s-buf >= 3)
  2336. XX                        write(1, buf, s-buf-2);
  2337. XX                    kill(cpid, 9);
  2338. XX                    while (wait((int *)0) != cpid)
  2339. XX                        ;
  2340. XX                    break;
  2341. XX                }
  2342. XX            }
  2343. XX        }
  2344. XX        write(1, buf, len);
  2345. XX    }
  2346. XX    if (use_linemode) {
  2347. XX#ifdef USG
  2348. XX        cbreak();
  2349. XX#else
  2350. XX        crmode();
  2351. XX#endif
  2352. XX        nonl();
  2353. XX        noecho();
  2354. XX    }
  2355. XX    /* (void) signal(SIGINT, prev_func);  Use at your own risk */
  2356. XX    refresh();
  2357. XX    scrolled = TRUE;
  2358. XX    hitcr_continue();
  2359. XX    clearok(curscr, TRUE);
  2360. XX    redraw_screen((struct li_line *)0);
  2361. XX    move_cursor(screen.sc_lineno, screen.sc_column);
  2362. XX}
  2363. @//E*O*F rv_shell.c//
  2364. chmod u=rw,g=rw,o=rw $OUT
  2365.  
  2366. echo x - rv_sync.c
  2367. if test -f rv_sync.c ; then
  2368.     echo rv_sync.c exists, putting output in $$rv_sync.c
  2369.     OUT=$$rv_sync.c
  2370.     STATUS=1
  2371. else
  2372.     OUT=rv_sync.c
  2373. fi
  2374. sed 's/^XX//' > $OUT <<'@//E*O*F rv_sync.c//'
  2375. XX#include "rv.h"
  2376.  
  2377. XX/*
  2378. XX * Synchronize communication by sending a command
  2379. XX * with a recognizable response.
  2380. XX */
  2381.  
  2382. XXvoid
  2383. XXxmit_sync()
  2384. XX/*
  2385. XX * Transmit sync
  2386. XX *
  2387. XX * A sync consists of transmitting two f commands followed
  2388. XX * by an illegal command, and waiting to receive the file name echoed
  2389. XX * twice followed by a question mark.
  2390. XX */
  2391. XX{
  2392. XX    if (fputs("f\nf\nzzz\n", file.fi_fpout) == NULL)
  2393. XX        panic("Error while writing to ed\n\n");
  2394. XX}
  2395.  
  2396. XXboolean
  2397. XXrecv_sync(disp_flag)
  2398. XX/*
  2399. XX * Wait for sync to come back
  2400. XX *
  2401. XX * Returns TRUE if no errors received prior to sync, else
  2402. XX *     displays errors if disp_flag is TRUE.
  2403. XX */
  2404. XXboolean disp_flag;
  2405. XX{
  2406. XX    register char buf[512];
  2407. XX    register INT i, namematch = 0, errcount = 0;
  2408. XX    INT old_alarm;
  2409. XX    extern alarmring();
  2410.  
  2411. XX    old_alarm = alarm(RV_TIMEOUT);
  2412.  
  2413. XX    fflush(file.fi_fpout);
  2414. XX    for (;;) {
  2415. XX        if (fgets(buf, 511, file.fi_fpin) == NULL)
  2416. XX            panic("Error while reading from ed\n\n");
  2417. XX        /*
  2418. XX         * Strip trailing \n
  2419. XX         */
  2420. XX        if ((i = strlen(buf)) > 0 && buf[i-1] == '\n')
  2421. XX            buf[--i] = '\0';
  2422. XX        if (buf[0] == '?') {
  2423. XX            if (namematch > 1)
  2424. XX                goto found;
  2425. XX            /*
  2426. XX             * Display error
  2427. XX             */
  2428. XX            ++errcount;
  2429. XX            if (file.fi_sysv) {
  2430. XX                if (buf[1] != ' ' ||
  2431. XX                        file.fi_cray == FALSE)
  2432. XX                    fgets(buf, 511, file.fi_fpin);
  2433. XX                if (disp_flag)
  2434. XX                    botprint(TRUE, "%s", buf);
  2435. XX            }
  2436. XX            else
  2437. XX                if (disp_flag)
  2438. XX                    botprint(TRUE, "Failed ");
  2439. XX            namematch = 0;
  2440. XX            continue;
  2441. XX        }
  2442. XX        /*
  2443. XX         * Look for file name echoed twice
  2444. XX         */
  2445. XX        if (strcmp(buf, file.fi_name) == 0) 
  2446. XX            ++namematch;
  2447. XX        else
  2448. XX            namematch = 0;
  2449. XX        if (namematch >= 2) {
  2450. XX            (void) fgets(buf, 511, file.fi_fpin);
  2451. XX            if ((i = strlen(buf)) > 0 && buf[i-1] == '\n')
  2452. XX                buf[--i] = '\0';
  2453. XX            /*
  2454. XX             * Look for question mark
  2455. XX             */
  2456. XX            if (buf[0] == '?') {
  2457. XX        found:
  2458. XX                if (file.fi_sysv &&
  2459. XX                    (buf[1] != ' ' || file.fi_cray == FALSE))
  2460. XX                    /*
  2461. XX                     * Skip error msg
  2462. XX                     */
  2463. XX                    fgets(buf, 511, file.fi_fpin);
  2464. XX                break;
  2465. XX            }
  2466. XX            else {
  2467. XX                if (disp_flag > 1)
  2468. XX                    botprint(FALSE, "%s", file.fi_name);
  2469. XX                if (strcmp(buf, file.fi_name)) {
  2470. XX                    if (disp_flag > 1)
  2471. XX                        botprint(FALSE, "%s", file.fi_name);
  2472. XX                    namematch = 0;
  2473. XX                }
  2474. XX            }
  2475. XX        }
  2476. XX        if (disp_flag > 1 && namematch == 0)
  2477. XX            botprint(FALSE, "%s", buf);
  2478. XX    }
  2479. XX    alarm(old_alarm);
  2480.  
  2481. XX    return (errcount == 0);
  2482. XX}
  2483. @//E*O*F rv_sync.c//
  2484. chmod u=rw,g=rw,o=rw $OUT
  2485.  
  2486. echo x - rv_undo.c
  2487. if test -f rv_undo.c ; then
  2488.     echo rv_undo.c exists, putting output in $$rv_undo.c
  2489.     OUT=$$rv_undo.c
  2490.     STATUS=1
  2491. else
  2492.     OUT=rv_undo.c
  2493. fi
  2494. sed 's/^XX//' > $OUT <<'@//E*O*F rv_undo.c//'
  2495. XX#include "rv.h"
  2496.  
  2497. XXvoid
  2498. XXrv_undo()
  2499. XX/*
  2500. XX * undo last change
  2501. XX *
  2502. XX * undo is accomplished by deleting the last inserted text, and
  2503. XX * restoring the last deleted text, both of which are assumed
  2504. XX * to start at the same row,col position.
  2505. XX */
  2506. XX{
  2507. XX    struct ya_yank     *yank, *save_yank;
  2508. XX    boolean deleted;
  2509. XX    void rv_linecmd();
  2510. XX    INT direction = -1;
  2511.  
  2512. XX    if (ed_undo) {
  2513. XX        rv_linecmd("u");
  2514. XX        ed_undo = TRUE;
  2515. XX        return;
  2516. XX    }
  2517. XX        
  2518. XX    yank = &yank_array[0];
  2519. XX    save_yank = &yank_array[NUM_YANK_BUFS-1];
  2520.  
  2521. XX    /*
  2522. XX     * See if there is something to undo
  2523. XX     */
  2524. XX    if (undo.un_deleted == FALSE && undo.un_inserted == FALSE) {
  2525. XX        flash();
  2526. XX        errflag = 1;
  2527. XX        return;
  2528. XX    }
  2529.  
  2530. XX    /*
  2531. XX     * Save previous yanked (deleted) text
  2532. XX     */
  2533. XX    copy((char *)save_yank, (char *)yank, sizeof(struct ya_yank));
  2534. XX    if (yank->ya_text) {
  2535. XX        save_yank->ya_text = xalloc(strlen(yank->ya_text)+1);
  2536. XX        strcpy(save_yank->ya_text, yank->ya_text);
  2537. XX    }
  2538. XX    deleted = undo.un_deleted;
  2539. XX    undo.un_deleted = FALSE;
  2540.  
  2541. XX    if (undo.un_firstline > file.fi_numlines) {
  2542. XX        direction = 1;
  2543. XX        undo.un_firstline = file.fi_numlines;
  2544. XX    }
  2545.  
  2546. XX    move_abs_cursor(undo.un_firstline, 0);
  2547. XX    /*
  2548. XX     * Delete last inserted text
  2549. XX     */
  2550. XX    if (undo.un_inserted) {
  2551. XX        register struct sc_screen *sc;
  2552.  
  2553. XX        sc = &screen;
  2554. XX        sc->sc_firstline = undo.un_firstline;
  2555. XX        sc->sc_lastline = undo.un_lastline;
  2556. XX        if (undo.un_validcol == FALSE)
  2557. XX            sc->sc_validcol = FALSE;
  2558. XX        else {
  2559. XX            sc->sc_validcol = TRUE;
  2560. XX            sc->sc_firstcol = undo.un_firstcol;
  2561. XX            sc->sc_lastcol = undo.un_lastcol;
  2562. XX        }
  2563. XX        undo.un_inserted = FALSE;
  2564. XX        delete();
  2565. XX    }
  2566. XX    /*
  2567. XX     * Restore last deleted text
  2568. XX     */
  2569. XX    if (deleted && save_yank->ya_type != YANK_EMPTY) {
  2570. XX        move_abs_cursor(undo.un_firstline, 0);
  2571. XX        if (save_yank->ya_type == YANK_COLS)
  2572. XX            screen.sc_column = undo.un_firstcol-1;
  2573. XX        yank_cmd = '$';
  2574. XX        put(direction);
  2575. XX    }
  2576.  
  2577. XX    /*
  2578. XX     * Free saved yank text
  2579. XX     */
  2580. XX    if (save_yank->ya_text) {
  2581. XX        free(save_yank->ya_text);
  2582. XX        save_yank->ya_text = NULL;
  2583. XX    }
  2584. XX    save_yank->ya_type = YANK_EMPTY;
  2585. XX}
  2586.  
  2587.  
  2588.  
  2589. XXvoid
  2590. XXsave_Undo()
  2591. XX/*
  2592. XX * Save current line into Undo buffer
  2593. XX */
  2594. XX{
  2595. XX    register struct li_line   *line;
  2596. XX    register struct sc_screen *sc;
  2597.  
  2598. XX    sc = &screen;
  2599. XX    line = sc->sc_curline;
  2600. XX    file.fi_modified = TRUE;
  2601. XX    if (sc->sc_origline.li_text == NULL) {
  2602. XX        /*
  2603. XX         * Copy line into Undo buffer
  2604. XX         */
  2605. XX        sc->sc_origline.li_text = xalloc(line->li_width+1);
  2606. XX        sc->sc_origline.li_segments = line->li_segments;
  2607. XX        sc->sc_origline.li_width = line->li_width;
  2608. XX        strcpy(sc->sc_origline.li_text, line->li_text);
  2609. XX    }
  2610. XX}
  2611.  
  2612.  
  2613. XXvoid
  2614. XXtoss_undo()
  2615. XX/*
  2616. XX * Forget last undo operation
  2617. XX */
  2618. XX{
  2619. XX    struct ya_yank *yank;
  2620.  
  2621. XX    yank = &yank_array[0];
  2622. XX    undo.un_inserted = FALSE;
  2623. XX    undo.un_deleted = FALSE; 
  2624. XX    undo.un_validcol = FALSE;
  2625. XX    if (yank->ya_text) {
  2626. XX        free(yank->ya_text);
  2627. XX        yank->ya_text = NULL;
  2628. XX    }
  2629. XX    yank->ya_type = YANK_EMPTY;
  2630. XX    ed_undo = FALSE;
  2631. XX}
  2632. @//E*O*F rv_undo.c//
  2633. chmod u=rw,g=rw,o=rw $OUT
  2634.  
  2635. echo Inspecting for damage in transit...
  2636. temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
  2637. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  2638. cat > $temp <<\!!!
  2639.      500    1357   10031 rv_insert.c
  2640.      324     848    5971 rv_linecmd.c
  2641.      153     375    3006 rv_misc.c
  2642.      280     887    6189 rv_move.c
  2643.      146     365    3019 rv_openline.c
  2644.       91     256    2163 rv_put.c
  2645.      107     315    2256 rv_redraw.c
  2646.       95     238    1757 rv_redraw_ln.c
  2647.       81     239    1642 rv_scroll.c
  2648.       83     234    1684 rv_scroll_bk.c
  2649.      230     748    4959 rv_search.c
  2650.      112     298    2092 rv_shell.c
  2651.      108     321    2191 rv_sync.c
  2652.      137     326    2671 rv_undo.c
  2653.     2447    6807   49631 total
  2654. !!!
  2655. wc $FILES | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  2656. if test -s $dtemp ; then
  2657.     echo "Ouch [diff of wc output]:"
  2658.     cat $dtemp
  2659.     STATUS=1
  2660. elif test $STATUS = 0 ; then
  2661.     echo "No problems found."
  2662. else
  2663.     echo "WARNING -- PROBLEMS WERE FOUND..."
  2664. fi
  2665. exit $STATUS
  2666.